TwitchClone / src / pages / index.tsx
index.tsx
Raw
import { type NextPage } from "next";
import Head from "next/head";
import { signIn, signOut, useSession } from "next-auth/react";
import Navbar from "../components/navbar/navbarParent";
import { api } from "../utils/api";
import { useEffect, useState } from "react";
import Sidebar from "../components/sidebar/sidebarParent";
import { CategoryButton } from "../components/cards/categoryCard";
import { baseCategories } from "../utils/helpers/categories";
import CategoryCards from "../components/cards/categoryCards";
import classNames from "../utils/helpers/className";
import { CarouselTwo } from "../components/spotlightSliderTwo";
import SuggestedStreamers from "../components/suggestedStreamer";
import { useUser } from "../hooks/useUser";
import userToUserProfile from "../utils/helpers/userToUserProfile";
import { User } from "@prisma/client";
import { simFollowing } from "../utils/helpers/user";
import { UserSchema } from "../types/user";
import Link from "next/link";
import { useRoomDataContext } from "../utils/context/RoomDataContext";
// import { determineFollowing } from "../utils/helpers/determineFollowing";
// import { isDataEqual } from "../utils/helpers/isDataEqual";
import router, { useRouter } from "next/router";
import UserContent from "../components/userContent";
import { isAdmin } from "../utils/helpers/admin.ts";
import Image from "next/image";
import Bandaid from "../components/bandaid";

type RoomDataSchema = {
  userData: UserSchema;
  roomId?: string;
  streamerId?: string;
};

type FollowingType = {
  id: string;
  followerId: string;
  followingId: string;
  createdAt: Date;
}[];

const Home: NextPage = () => {
  // const hello = api.example.hello.useQuery({ text: "from tRPC" });
  const { data: user, status } = useSession();
  const [userProfile_, setUserProfile_] = useState<null | UserSchema>(null);
  const [user_, setUser_] = useState<User | null>(null);
  const [expand, setExpand] = useState(false);
  const [searchTab, setSearchTab] = useState(false);
  const [opened, setOpened] = useState(false);
  const userP = useUser();
  const userProfile = userToUserProfile(userP);
  const userEmail = user?.user?.email;
  const [roomId, setRoomId] = useState("");
  // const [roomData_, setRoomData_] = useState<RoomDataSchema | null>(null);
  const [initUserDbData, setInitUserDbData] = useState<UserSchema | null>(null);
  // const [uploadId, setUploadId] = useState<string | null>(null);
  // const [uploadUrl, setUploadUrl] = useState<string | null>(null);
  // const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const dbProfileQuery = api.lambda.getUserInfo.useQuery({
    email: userEmail || "",
  });
  // const [allUsers, setAllUsers] = useState<UserSchema[] | null>(null);
  const { roomData, setRoomData, userData, setUserData } = useRoomDataContext();
  const [allowedUsers, setAllowedUsers] = useState<string[]>([]);
  const [allowed, setAllowed] = useState(false);
  // const updateFollowingMutation = api.lambda.updateFollowing.useMutation();
  // const [isFollowing, setIsFollowing] = useState(userData.following.includes(streamerData.data?.id));
  // const [isAllowed, setIsAllowed] = useState(false);
  const allowedAdminEmails = [
    "grocedj@gmail.com",
    "blackmarketpublishing@gmail.com",
  ];

  const allowedUsers_ = [
    "grocedj@gmail.com",
    "blackmarketpublishing@gmail.com",
    "cierrapin08@gmail.com",
    "grocedb0815@gmail.com",
  ];

  // const addDemoUsersMutation = api.lambda.addDemoUsers.useMutation();
  const userList = api.lambda.fetchAllUsers.useQuery();
  // const [count, setCount] = useState(0);
  // const router = useRouter();
  // console.log(dbProfileQuery.data, "dbProfileQuery.data");
  // console.log(userProfile_, "userProfile_");
  // const allowedUsers = [
  //   "user1@example.com",
  //   "user2@example.com",
  //   // add more allowed users here
  // ];
  const isAllowedUser = (email: string) => {
    return allowedUsers_.includes(email);
  };
  // const checkIfAdmin = () => {
  //   return isAdmin(user?.user?.email);
  // };

  const checkIfAdmin = () => {
    if (!user?.user?.email) {
      return false;
    }

    return allowedAdminEmails.includes(user.user.email);
  };

  const handleAdminPage = async () => {
    if (checkIfAdmin()) {
      await router.push("/admin");
    } else {
      alert("You do not have access to the admin page.");
    }
  };

  // const handleAdminPage = () => {
  //   router.push('/admin');
  // };

  const handleLogin = async (e: React.MouseEvent<HTMLDivElement>) => {
    e.preventDefault();
    console.log("logging in");
    await signIn("google");
  };

  if (
    dbProfileQuery.data &&
    dbProfileQuery.data.followers &&
    !initUserDbData &&
    !userProfile_
  ) {
    setInitUserDbData((prev) => {
      if (!prev && dbProfileQuery.data) {
        return {
          id: dbProfileQuery.data.id,
          name: dbProfileQuery.data.name || "",
          email: dbProfileQuery.data.email || "",
          following: dbProfileQuery.data.following || [],
          followers: dbProfileQuery.data.followers || [],
          image: dbProfileQuery.data.image || "",
        };
      }
      if (!prev || !dbProfileQuery.data || !dbProfileQuery) return null;
      return {
        id: prev.id,
        name: prev.name,
        email: prev.email,
        following: dbProfileQuery.data.followers,
        image: prev.image,
      };
    });
  }
  console.log("allUsers", userList.data);
  // Inside home page component
  useEffect(() => {
    if (!allowedUsers) {
      setAllowedUsers(allowedUsers_);
    }

    setRoomData((prev: RoomDataSchema | null) => {
      if (!prev) {
        return null;
      }
      return {
        ...prev,
        // Reset the properties related to the selected stream
        selectedVideoId: undefined,
        assetId: undefined,
        assetUrl: undefined,
        playbackId: undefined,
        playbakUrl: undefined,
        streamerId: undefined,
        streamerInfo: undefined,
        setUserProfile_,
      };
    });
  }, []);

  useEffect(() => {
    console.log("allowed", allowed);
    if (user?.user) {
      setUser_({
        id: user.user.id,
        name: user.user.name || "",
        email: user.user.email || "",
        // Add any other properties you need for the chat functionality
      } as User);
      if (
        user &&
        user.user &&
        user.user.email &&
        isAllowedUser(user.user.email)
      ) {
        console.log("allowed");
        setAllowed(true);
      }
      if (
        user &&
        user.user &&
        user.user.email &&
        !isAllowedUser(user.user.email)
      ) {
        console.log("notallowed");
        setAllowed(false);
      }
    } else {
      return;
    }
  }, [user, allowed]);

  useEffect(() => {
    console.log("firing", userProfile_, initUserDbData);
    const arr: FollowingType = [];
    const data_ = simFollowing.map((follower) => {
      arr.push({
        id: follower.id.toString(),
        followerId: follower.id.toString(),
        followingId: user?.user?.id || "",
        createdAt: new Date(),
      });
    });
    data_;
    if (!userProfile_ || !initUserDbData) {
      if (userProfile_ === null) {
        if (
          initUserDbData &&
          initUserDbData.following &&
          userProfile_ === null &&
          user &&
          user.user &&
          user.user.id
        ) {
          setUserProfile_({
            id: user?.user?.id,
            name: user?.user?.name || "",
            email: user?.user?.email || "",
            following: initUserDbData.following || [],
            image: user?.user?.image || "",
          });
          console.log(user.user.id);
          //set context
          setUserData({
            id: user?.user?.id,
            name: user?.user?.name || "",
            email: user?.user?.email || "",
            following: initUserDbData.following || [],
            image: user?.user?.image || "",
          });
          //set context
          setRoomData({
            userData: {
              id: user?.user?.id,
              name: user?.user?.name || "",
              email: user?.user?.email || "",
              following: initUserDbData.following || [],
              image: user?.user?.image || "",
            },
            setUserProfile_,
            // roomId,
          });
          console.log("all set");
          // return setUserProfile_(initUserDbData);
        }
        // console.log(updatedFollowing);
        return;
      }
    }
  }, [user_, userProfile_, initUserDbData]);

  useEffect(() => {
    console.log(searchTab);
    if (searchTab) {
      setOpened(true);
    } else {
      setOpened(false);
    }
  }, [searchTab]);

  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    console.log("The link was clicked.");
    setSearchTab((prev) => !prev);
  };

  const mobileSearchProps = {
    opened: opened,
    handleClick: handleClick,
    searchTab: searchTab,
    setSearchTab: setSearchTab,
  };
  console.log("userCheck", user?.user);
  console.log("userCheck", user?.user?.email);
  console.log(isAllowedUser(user?.user?.email || ""));
  console.log("allowed", allowed);
  return (
    <div className="scrollbar-hide">
      <Head>
        <title>My Twitch clone</title>
        <meta name="description" content="my twitch app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        {user && user.user && allowed ? (
          <div className=" min-w-screen flex min-h-screen flex-1 flex-col  bg-[#0e0e10] text-base scrollbar-hide">
            <div className="sticky top-0 z-30 h-full max-h-[3.00rem] scrollbar-hide md:min-h-full">
              <Navbar
                profile={userProfile}
                mobile={false}
                search={false}
                customCombo={false}
                props={mobileSearchProps}
              />
            </div>
            <div className=" relative flex min-h-screen w-full flex-1 flex-grow flex-col scrollbar-hide">
              <div className="absolute  -top-[3rem] left-0 z-20 flex min-h-[calc(100vh+3rem)] grow flex-col bg-[#1f1f23] scrollbar-hide">
                <div className="sticky top-[2.5rem] left-0">
                  <Sidebar
                    user={userProfile}
                    expand={expand}
                    setExpand={setExpand}
                  />
                </div>
              </div>
              <div className=" inline-flex min-h-screen flex-col">
                <div
                  className={classNames(
                    expand ? "w-[calc(100%-12rem)]" : "w-[calc(100%-2.2rem)]",
                    "ml-auto flex h-[14.0rem]  grow justify-end xs:max-sm:mb-[1.8rem]"
                  )}
                >
                  <div
                    className={classNames(
                      expand ? "pl-[13.438rem]" : "pl-[2.2rem]",
                      "z-10 flex h-[100%] w-full grow flex-col items-start justify-start pt-3  2xs:max-sm:px-0 sm:px-0"
                    )}
                  >
                    {userProfile && <CarouselTwo />}
                  </div>
                </div>
                <SuggestedStreamers newExpand={expand} mobile={false} />
                <CategoryCards newExpand={expand} mobile={false} />
                <div
                  className={classNames(
                    expand ? "pl-[13.438rem]" : "pl-[2.2rem]",
                    "z-10 flex min-h-[10%] w-full flex-col items-start justify-start  px-10 pb-10 pt-1"
                  )}
                >
                  <div className="flex w-full flex-1 flex-grow flex-wrap items-start justify-around gap-2 pl-6 max-lg:justify-start">
                    {baseCategories.map((category, index) => {
                      return (
                        <CategoryButton
                          key={`baseCat-${index}`}
                          category={category}
                        />
                      );
                    })}
                  </div>
                </div>
                <div
                  className={classNames(
                    expand ? "pl-[13.438rem]" : "pl-[2.2rem]",
                    "z-10 flex h-auto w-full grow flex-col items-start justify-start px-10 pb-10"
                  )}
                >
                  <div className="pl-6">
                    <div className="text-base">etc... </div>
                    <button className="rounded-md border-2 border-transparent bg-violet-600 px-2 py-2 hover:border-white hover:bg-violet-500">
                      remove me
                      {/* <Link href={`/streams/${roomId}`}>Demo Stream</Link> */}
                    </button>
                  </div>
                  {userList.data &&
                    userList.data.map((user) => {
                      // Handle the case when the user has no videos
                      if (user.videos.length === 0) {
                        return null;
                      }
                      // Find the newest video roomId
                      const mostRecentVideo = user.videos.reduce(
                        (prev, curr) =>
                          !prev
                            ? curr
                            : prev.createdAt > curr.createdAt
                            ? prev
                            : curr,
                        user.videos[0]
                      );
                      return (
                        mostRecentVideo && (
                          <UserContent
                            user={user}
                            roomId={user.id}
                            playbackId={mostRecentVideo.playbackId}
                            selectedId={user.id}
                            setRoomId={setRoomId}
                          />
                        )
                      );
                    })}
                  <div className="flex h-full w-1/3 grow pb-5">
                    {checkIfAdmin() && (
                      <button
                        onClick={() => void handleAdminPage()}
                        className="rounded bg-blue-500 py-2 px-4 font-bold text-white hover:bg-blue-700"
                      >
                        Go to Admin Page
                      </button>
                    )}
                  </div>

                  <div className="flex w-full items-start"></div>
                </div>
              </div>
            </div>
          </div>
        ) : (
          <div className="flex flex-col items-center pt-8">
            <div className="relative flex w-full flex-col items-center justify-center">
              <div className="absolute bottom-[4.5rem] flex translate-x-[-11.5em]">
                <Image
                  src={`/bandaid.png`}
                  alt="bandaid-logo"
                  width={250}
                  height={120}
                  className="w-[5.05rem] rotate-[-48deg]"
                />
              </div>
              <Image
                src={`/TwitchExtruded.png`}
                // fill={'#ffffff'}
                alt="Twitch Logo"
                width={350}
                height={200}
                className="w-[25.45rem] max-w-[38.95rem]"
              />
            </div>
            <div className="pt-4 text-center text-xl text-white">
              {user && user.user
                ? `You don't have access to this content.`
                : `You need to be logged in to view this content.`}
              <div
                onClick={(e) => void handleLogin(e)}
                className={classNames(
                  user && user.user
                    ? "disabled cursor-not-allowed"
                    : "active cursor-pointer",
                  " underline"
                )}
              >
                {user && user.user ? "Not Authorized" : "Log in"}
              </div>
            </div>
            {/* <div className="w-[56vmin] border-[0.5vmin] border-[rgb(3,169,244)] relative cursor-pointer">
  <div className=" bg-gradient-radial from-purple-500">
    <h3 className="card-title">I know exactly what I'm doing</h3>
    <h4 className="card-subtitle"></h4>
  </div>
  <i className="fa-solid fa-hat-witch card-icon"></i>
</div> */}
          </div>
        )}
      </main>
    </div>
  );
};

export default Home;

const AuthShowcase: React.FC = () => {
  const { data: sessionData } = useSession();

  const { data: secretMessage } = api.example.getSecretMessage.useQuery(
    undefined, // no input
    { enabled: sessionData?.user !== undefined }
  );

  return (
    <div className="flex flex-col items-center justify-center gap-4">
      <p className="text-center text-2xl text-white">
        {sessionData && <span>Logged in as {sessionData.user?.name}</span>}
        {secretMessage && <span> - {secretMessage}</span>}
      </p>
      <button
        className="rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20"
        onClick={sessionData ? () => void signOut() : () => void signIn()}
      >
        {sessionData ? "Sign out" : "Sign in"}
      </button>
    </div>
  );
};