Skip to content

Commit

Permalink
Move router to top level, functional sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
P-man2976 committed Oct 15, 2023
1 parent d300992 commit e4d4cc3
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 217 deletions.
17 changes: 17 additions & 0 deletions packages/react/src/components/channel/NavigateToMusicdex.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Navigate, useParams } from "react-router-dom";

export function NavigateToMusicdex() {
const { id } = useParams();
const isStaging = location.origin.includes("staging");

return (
<Navigate
to={
isStaging
? `https://music-staging.holodex.net/channel/${id}`
: `https://music.holodex.net/channel/${id}`
}
replace
/>
);
}
18 changes: 10 additions & 8 deletions packages/react/src/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import { darkAtom } from "@/hooks/useTheme";
import { Button } from "@/shadcn/ui/button";
import { userAtom } from "@/store/auth";
import { useAtom, useAtomValue } from "jotai";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";

interface HeaderProps {
onClick: () => void;
id: string;
}

export function Header({ onClick, id }: HeaderProps) {
const { t } = useTranslation();
const [dark, toggle] = useAtom(darkAtom);
const user = useAtomValue(userAtom);

Expand All @@ -17,18 +20,15 @@ export function Header({ onClick, id }: HeaderProps) {
id={id}
className="bg-base-2 flex items-center px-8 py-auto gap-4 sticky top-0 z-40"
>
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2 rounded"
onClick={onClick}
>
<Button size="icon-lg" variant="ghost" onClick={onClick}>
<div className="i-heroicons:bars-3 rounded-md px-3 py-3 " />
</button>
</Button>
<div className="justify-start py-1 pl-3 text-xl">Hololive</div>
<div className="i-heroicons:chevron-down py-5" />
<div className="flex flex-grow" />
<Button
size='icon-lg'
variant='ghost'
size="icon-lg"
variant="ghost"
className="p-2"
onClick={() => toggle(!dark)}
>
Expand All @@ -40,7 +40,9 @@ export function Header({ onClick, id }: HeaderProps) {
src={`https://avatars.dicebear.com/api/jdenticon/${user.id}.svg`}
/>
) : (
<button>Login</button>
<Button asChild>
<Link to="/login">{t("Login")}</Link>
</Button>
)}
</header>
);
Expand Down
49 changes: 30 additions & 19 deletions packages/react/src/components/layout/Frame.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import './Frame.scss'
import { RouterProvider } from 'react-router-dom'
import router from '@/routes/router'
import { ReactPropTypes, useEffect } from 'react'
import { Sidebar } from '@/components/sidebar/sidebar'
import { isFloatingAtom, isMobileAtom, onResizeAtom, sidebarOpenAtom, sidebarShouldBeFullscreenAtom, toggleAtom } from '@/hooks/useFrame'
import "./Frame.scss";
import { Navigate, Outlet, useLocation, useNavigate } from "react-router-dom";
import { ReactPropTypes, useEffect } from "react";
import { Sidebar } from "@/components/sidebar/sidebar";
import {
isFloatingAtom,
isMobileAtom,
onResizeAtom,
sidebarOpenAtom,
sidebarShouldBeFullscreenAtom,
toggleAtom,
} from "@/hooks/useFrame";
import { useAtomValue, useSetAtom } from "jotai/react";
import { darkAtom } from '@/hooks/useTheme'
import { Header } from "@/components/header/header"
import { Toaster } from '@/shadcn/ui/toaster'
import clsx from 'clsx'
import { darkAtom } from "@/hooks/useTheme";
import { Header } from "@/components/header/header";
import { Toaster } from "@/shadcn/ui/toaster";
import clsx from "clsx";
import { orgAtom } from "@/store/org";

export function Frame() {
const location = useLocation();
const toggle = useSetAtom(toggleAtom);
const resize = useSetAtom(onResizeAtom);
const dark = useAtomValue(darkAtom);
const org = useAtomValue(orgAtom);

useEffect(() => {
window.addEventListener("resize", resize);
Expand All @@ -26,15 +35,17 @@ export function Frame() {
const fs = useAtomValue(sidebarShouldBeFullscreenAtom);
console.log(fs);

if (location.pathname === "/") return <Navigate to={`/org/${org}`} />;

const mainClasses = clsx({
'mobile-footer': isMobile,
'sidebar-static': !floating,
'sidebar-floating': floating,
'sidebar-open': open,
'sidebar-closed': !open,
'sidebar-fullscreen': fs,
'dark': dark,
})
"mobile-footer": isMobile,
"sidebar-static": !floating,
"sidebar-floating": floating,
"sidebar-open": open,
"sidebar-closed": !open,
"sidebar-fullscreen": fs,
dark: dark,
});

return (
<div className={mainClasses} id="layout">
Expand All @@ -43,7 +54,7 @@ export function Frame() {
</aside>
<Header onClick={toggle} id="header" />
<main className="">
<RouterProvider router={router}></RouterProvider>
<Outlet />
</main>
{isMobile && <footer className="">Footer</footer>}
<Toaster />
Expand Down
139 changes: 95 additions & 44 deletions packages/react/src/components/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { darkAtom } from "@/hooks/useTheme";
import { cn } from "@/lib/utils";
import { Button } from "@/shadcn/ui/button";
import { useAtom } from "jotai";
import { useAtomValue } from "jotai";
import { OrgSelectorCombobox } from "../org/OrgPicker";
import { useTranslation } from "react-i18next";
import { Link, useLocation } from "react-router-dom";
import { orgAtom } from "@/store/org";
import { HTMLAttributes } from "react";
import { isMobileAtom } from "@/hooks/useFrame";
// import { ScrollArea } from "@/shadcn/ui/scroll-area"

interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {
Expand All @@ -12,7 +15,7 @@ interface SidebarProps extends React.HTMLAttributes<HTMLDivElement> {

export function Sidebar({ className, id, onClose }: SidebarProps) {
const { t } = useTranslation();
const [dark, toggle] = useAtom(darkAtom);
const org = useAtomValue(orgAtom);

return (
<div className={cn("pb-12 border-r-base-5 border-r", className)} id={id}>
Expand All @@ -31,54 +34,64 @@ export function Sidebar({ className, id, onClose }: SidebarProps) {
<OrgSelectorCombobox />
<h2 className="mb-2 px-4 font-semibold tracking-tight">Hololive</h2>
<div className="space-y-1">
<Button className="w-full justify-start" variant="default">
<div className="i-heroicons:home"></div>
{t("Home")}
</Button>
<Button className="w-full justify-start" variant="ghost">
<span className="i-heroicons:user-group"></span>
{t("Channels")}
</Button>
<SidebarItem
onClose={onClose}
label="Home"
href={`/org/${org}`}
icon="i-heroicons:home"
/>
<SidebarItem
onClose={onClose}
label="Channels"
href={`/org/${org}/channels`}
icon="i-heroicons:user-group"
/>
</div>
</div>
{/* <hr className="border-base" /> */}
<div className="px-3 py-2">
{/* <h2 className="mb-2 px-4 font-semibold tracking-tight">Holodex</h2> */}
<div className="space-y-2">
<Button className="w-full justify-start" variant="ghost">
<span className="i-heroicons:heart"></span>
{t("Favorites")}
</Button>
<Button className="w-full justify-start" variant="ghost">
<span className="i-heroicons:rectangle-group"></span>
{t("Multiview")}
</Button>
<Button className="w-full justify-start" variant="ghost">
<span className="i-heroicons:musical-note"></span>
{t("Musicdex")}
</Button>
<SidebarItem
label="Favorites"
icon="i-heroicons:heart"
href="/favorites"
onClose={onClose}
/>
<SidebarItem
label="Multiview"
icon="i-heroicons:rectangle-group"
href="/multiview"
onClose={onClose}
/>
<SidebarItem
label="Musicdex"
icon="i-heroicons:musical-note"
href="https://music.holodex.net"
onClose={onClose}
/>
<hr className="border-base" />
<Button
className="w-full justify-start text-base-11"
variant="ghost"
>
<span className="i-heroicons:queue-list"></span>
{t("Playlist")}
</Button>
<Button
className="w-full justify-start text-base-11"
variant="ghost"
>
<span className="i-heroicons:cog-6-tooth"></span>
{t("Settings")}
</Button>
<Button
className="w-full justify-start text-base-11"
variant="ghost"
>
<span className="i-heroicons:information-circle"></span>
{t("About")}
</Button>
<SidebarItem
className="text-base-11"
label="Playlist"
icon="i-heroicons:queue-list"
href="/playlists"
onClose={onClose}
/>
<SidebarItem
className="text-base-11"
label="Settings"
icon="i-heroicons:cog-6-tooth"
href="/settings"
onClose={onClose}
/>
<SidebarItem
className="text-base-11"
label="About"
icon="i-heroicons:information-circle"
href="/about"
onClose={onClose}
/>
</div>
</div>
<div className="py-2">
Expand Down Expand Up @@ -128,3 +141,41 @@ export function Sidebar({ className, id, onClose }: SidebarProps) {
</div>
);
}

function SidebarItem({
className,
onClose,
icon,
label,
href,
}: {
className?: HTMLAttributes<HTMLButtonElement>["className"];
onClose: () => void;
icon: HTMLAttributes<HTMLSpanElement>["className"];
label: string;
href: string;
}) {
const { t } = useTranslation();
const location = useLocation();
const isMobile = useAtomValue(isMobileAtom);

const isHere = href === location.pathname;

return (
<Button
asChild
className={cn(
"w-full justify-start",
{ "text-white": isHere },
className,
)}
variant={isHere ? "default" : "ghost"}
onClick={isMobile ? onClose : undefined}
>
<Link to={href}>
<span className={icon}></span>
{t(label)}
</Link>
</Button>
);
}
29 changes: 17 additions & 12 deletions packages/react/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { GoogleOAuthProvider } from "@react-oauth/google";
import { HelmetProvider } from "react-helmet-async";
import "./index.css";
import "uno.css";
import { Frame } from "./components/layout/Frame.tsx";
import { useThemeInit } from "./hooks/useTheme.ts";
import { useThemeInit } from "./hooks/useTheme";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import "./lib/i18n";
import { RouterProvider } from "react-router-dom";
import router from "./routes/router";

const GOOGLE_CLIENT_ID =
"275540829388-87s7f9v2ht3ih51ah0tjkqng8pd8bqo2.apps.googleusercontent.com";
Expand All @@ -15,23 +18,25 @@ const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnMount: false,
refetchOnWindowFocus: false
}
}
refetchOnWindowFocus: false,
},
},
});

function App() {
useThemeInit();
return <Frame />;
return <RouterProvider router={router} />;
}

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<GoogleOAuthProvider clientId={GOOGLE_CLIENT_ID}>
<App />
</GoogleOAuthProvider>
</QueryClientProvider>
<HelmetProvider>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<GoogleOAuthProvider clientId={GOOGLE_CLIENT_ID}>
<App />
</GoogleOAuthProvider>
</QueryClientProvider>
</HelmetProvider>
</React.StrictMode>,
);
12 changes: 12 additions & 0 deletions packages/react/src/routes/about.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Outlet } from "react-router-dom";


export default function About () {

return (
<div>
About
<Outlet />
</div>
)
}
12 changes: 12 additions & 0 deletions packages/react/src/routes/channel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Outlet } from "react-router-dom";


export default function Channel () {

return (
<div>
Channel
<Outlet />
</div>
)
}
Loading

0 comments on commit e4d4cc3

Please sign in to comment.