From 0335b0ad81169232a3dbb1be1341fdcfce548645 Mon Sep 17 00:00:00 2001
From: Pinapelz <yukais@pinapelz.com>
Date: Tue, 2 Jun 2026 02:12:57 -0700
Subject: migrate to pocketbase backend + auth/login

---
 src/app/page.tsx | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 141 insertions(+), 3 deletions(-)

(limited to 'src/app/page.tsx')

diff --git a/src/app/page.tsx b/src/app/page.tsx
index f8e1c1b..7a9b718 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,5 +1,143 @@
-import { redirect } from "next/navigation";
+"use client";
+import { useEffect, useState } from "react";
+import { FaPlay, FaMusic, FaSearch } from "react-icons/fa";
+import { MdLibraryMusic } from "react-icons/md";
+import { useAuth } from "./context/auth";
+import pb from "./lib/pocketbase";
+import {
+  Root,
+  Navbar,
+  Logo,
+  LogoIcon,
+  NavCtaLink,
+  NavLeft,
+  NavCenter,
+  SearchBox,
+  SearchInput,
+  SearchButton,
+  NavRight,
 
-export default function HomePage() {
-  redirect("/typing");
+  GridContainer,
+  CardGrid,
+  Card,
+  ThumbnailWrapper,
+  Thumbnail,
+  PlayOverlay,
+  PlayCircle,
+  CardMeta,
+  CardInfo,
+  CardTitle,
+  CardSub,
+  EmptyState,
+  TypingGlobalStyle,
+} from "./page.styles";
+
+interface ChartRecord {
+  id: string;
+  title: string;
+  artist: string;
+  thumbnail: string;
+  lrc: string;
+  media: string;
+  offset: number;
+}
+
+
+export default function TypingPage() {
+  const { user, signOut } = useAuth();
+  const [charts, setCharts] = useState<ChartRecord[]>([]);
+  const [search, setSearch] = useState("");
+
+  useEffect(() => {
+    pb.collection("charts")
+      .getFullList<ChartRecord>({ sort: "-created" })
+      .then(setCharts)
+      .catch(console.error);
+  }, []);
+
+  const normalizedSearch = search.trim().toLowerCase();
+  const filtered = normalizedSearch
+    ? charts.filter(
+        (item) =>
+          item.title.toLowerCase().includes(normalizedSearch) ||
+          item.artist.toLowerCase().includes(normalizedSearch),
+      )
+    : charts;
+
+  return (
+    <>
+      <TypingGlobalStyle />
+      <Root>
+      <Navbar>
+        <NavLeft>
+          <Logo href="/">
+            <LogoIcon>
+              <MdLibraryMusic />
+            </LogoIcon>
+            TypingMIXX
+          </Logo>
+        </NavLeft>
+
+        <NavCenter>
+          <SearchBox>
+            <SearchInput
+              placeholder="Search typing charts..."
+              value={search}
+              onChange={(e) => setSearch(e.target.value)}
+            />
+            <SearchButton aria-label="Search">
+              <FaSearch />
+            </SearchButton>
+          </SearchBox>
+        </NavCenter>
+
+        <NavRight>
+          {user ? (
+            <>
+              <span style={{ fontSize: 13, color: "#b0b3bd", padding: "0 6px", maxWidth: 140, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
+                {user.username || user.name}
+              </span>
+              <NavCtaLink href="#" onClick={(e) => { e.preventDefault(); signOut(); }}>
+                Sign out
+              </NavCtaLink>
+            </>
+          ) : (
+            <NavCtaLink href="/signin">Sign in</NavCtaLink>
+          )}
+        </NavRight>
+      </Navbar>
+
+      <GridContainer>
+        <CardGrid>
+          {filtered.length === 0 ? (
+            <EmptyState>No results found.</EmptyState>
+          ) : (
+            filtered.map((item) => (
+              <Card key={item.id} href={`/game/${item.id}`} target="_blank" rel="noopener noreferrer">
+                <ThumbnailWrapper>
+                  {item.thumbnail ? (
+                    <Thumbnail src={item.thumbnail} alt={item.title} />
+                  ) : (
+                    <FaMusic />
+                  )}
+                  <PlayOverlay>
+                    <PlayCircle>
+                      <FaPlay />
+                    </PlayCircle>
+                  </PlayOverlay>
+                </ThumbnailWrapper>
+                <CardMeta>
+                  <CardInfo>
+                    <CardTitle>{item.title}</CardTitle>
+                    <CardSub>{item.artist}</CardSub>
+                  </CardInfo>
+                </CardMeta>
+              </Card>
+            ))
+          )}
+        </CardGrid>
+      </GridContainer>
+      </Root>
+    </>
+  );
 }
-- 
cgit v1.2.3

