-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: ✨ Implement dashboard feature.
- Create dashboard page. - Create dashboard navigation. - Create dashboard sidebar. - Create custom hook to manage dashboard sidebar state. - Improved auth service. - Update navbar and hint styling. Users can now access their own dashboard to manage stream, account, community, chat and settings like software integration.
- Loading branch information
1 parent
0e0244f
commit d961e7c
Showing
15 changed files
with
424 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { currentUser } from "@clerk/nextjs"; | ||
|
||
import { getUserByUsername } from "@/lib/user-service"; | ||
// import { StreamPlayer } from "@/components/stream-player"; | ||
|
||
interface CreatorPageProps { | ||
params: { | ||
username: string; | ||
}; | ||
} | ||
|
||
const CreatorPage = async ({ params }: CreatorPageProps) => { | ||
const externalUser = await currentUser(); | ||
const user = await getUserByUsername(params.username); | ||
|
||
if (!user || user.externalUserId !== externalUser?.id || !user.stream) { | ||
throw new Error("Unauthorized"); | ||
} | ||
|
||
return ( | ||
<div className="h-full"> | ||
{/* <StreamPlayer | ||
user={user} | ||
stream={user.stream} | ||
isFollowing | ||
/> */} | ||
</div> | ||
); | ||
}; | ||
|
||
export default CreatorPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
"use client"; | ||
|
||
import { useEffect } from "react"; | ||
import { useMediaQuery } from "usehooks-ts"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
import { useCreatorSidebar } from "@/store/use-creator-sidebar"; | ||
|
||
interface ContainerProps { | ||
children: React.ReactNode; | ||
} | ||
|
||
const Container = ({ children }: ContainerProps) => { | ||
const { collapsed, onCollapse, onExpand } = useCreatorSidebar( | ||
(state) => state | ||
); | ||
const matches = useMediaQuery(`(max-width: 1024px)`); | ||
|
||
useEffect(() => { | ||
if (matches) { | ||
onCollapse(); | ||
} else { | ||
onExpand(); | ||
} | ||
}, [matches, onCollapse, onExpand]); | ||
|
||
return ( | ||
<div | ||
className={cn("flex-1", collapsed ? "ml-[70px]" : "ml-[70px] lg:ml-60")} | ||
> | ||
{children} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Container; |
26 changes: 26 additions & 0 deletions
26
app/(dashboard)/u/[username]/_components/navbar/actions.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import Link from "next/link"; | ||
import { LogOut } from "lucide-react"; | ||
import { UserButton } from "@clerk/nextjs"; | ||
|
||
import { Button } from "@/components/ui/button"; | ||
|
||
const Actions = () => { | ||
return ( | ||
<div className="flex items-center justify-end gap-x-2"> | ||
<Button | ||
size="sm" | ||
variant="ghost" | ||
className="text-muted-foreground hover:text-primary" | ||
asChild | ||
> | ||
<Link href="/"> | ||
<LogOut className="h-5 w-5 mr-2" /> | ||
Exit | ||
</Link> | ||
</Button> | ||
<UserButton afterSignOutUrl="/" /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Actions; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import Actions from "./actions"; | ||
import Logo from "./logo"; | ||
|
||
const Navbar = () => { | ||
return ( | ||
<nav className="fixed top-0 w-full h-20 z-[49] bg-primary-foreground px-2 lg:px-4 flex justify-between items-center shadow-sm"> | ||
<Logo /> | ||
|
||
<Actions /> | ||
</nav> | ||
); | ||
}; | ||
|
||
export default Navbar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import Link from "next/link"; | ||
import Image from "next/image"; | ||
import { Poppins } from "next/font/google"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
|
||
const font = Poppins({ | ||
subsets: ["latin"], | ||
weight: ["200", "300", "400", "500", "600", "700", "800"], | ||
}); | ||
|
||
const Logo = () => { | ||
return ( | ||
<Link href="/"> | ||
<div className="flex items-center gap-x-4 hover:opacity-75 transition"> | ||
<div className="rounded-full mr-12 shrink-0 lg:mr-0 lg:shrink"> | ||
<Image | ||
src="/s3mer.svg" | ||
alt="S3mer logo" | ||
height={50} | ||
width={50} | ||
/> | ||
</div> | ||
|
||
<div className={cn("hidden lg:block", font.className)}> | ||
<p className="text-lg font-semibold">S3MER</p> | ||
<p className="text-xs text-muted-foreground">Your S3MER Dashboard</p> | ||
</div> | ||
</div> | ||
</Link> | ||
); | ||
}; | ||
|
||
export default Logo; |
14 changes: 14 additions & 0 deletions
14
app/(dashboard)/u/[username]/_components/sidebar/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import Toggle from "./toggle"; | ||
import Wrapper from "./wrapper"; | ||
import Navigation from "./navigation"; | ||
|
||
const Sidebar = () => { | ||
return ( | ||
<Wrapper> | ||
<Toggle /> | ||
<Navigation /> | ||
</Wrapper> | ||
); | ||
}; | ||
|
||
export default Sidebar; |
52 changes: 52 additions & 0 deletions
52
app/(dashboard)/u/[username]/_components/sidebar/nav-item.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
"use client"; | ||
|
||
import Link from "next/link"; | ||
import { LucideIcon } from "lucide-react"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
import { Button } from "@/components/ui/button"; | ||
import { Skeleton } from "@/components/ui/skeleton"; | ||
import { useCreatorSidebar } from "@/store/use-creator-sidebar"; | ||
|
||
interface NavItemProps { | ||
icon: LucideIcon; | ||
label: string; | ||
href: string; | ||
isActive: boolean; | ||
} | ||
|
||
const NavItem = ({ icon: Icon, label, href, isActive }: NavItemProps) => { | ||
const { collapsed } = useCreatorSidebar((state) => state); | ||
|
||
return ( | ||
<Button | ||
asChild | ||
variant="ghost" | ||
className={cn( | ||
"w-full h-12", | ||
collapsed ? "justify-center" : "justify-start", | ||
isActive && "bg-accent" | ||
)} | ||
> | ||
<Link href={href}> | ||
<div className="flex items-center gap-x-4"> | ||
<Icon className={cn("h-4 w-4", collapsed ? "mr-0" : "mr-2")} /> | ||
{!collapsed && <span>{label}</span>} | ||
</div> | ||
</Link> | ||
</Button> | ||
); | ||
}; | ||
|
||
export default NavItem; | ||
|
||
export const NavItemSkeleton = () => { | ||
return ( | ||
<li className="flex items-center gap-x-4 px-3 py-2"> | ||
<Skeleton className="min-h-[48px] min-w-[48px] rounded-md" /> | ||
<div className="flex-1 hidden lg:block"> | ||
<Skeleton className="h-6" /> | ||
</div> | ||
</li> | ||
); | ||
}; |
61 changes: 61 additions & 0 deletions
61
app/(dashboard)/u/[username]/_components/sidebar/navigation.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
"use client"; | ||
|
||
import { useUser } from "@clerk/nextjs"; | ||
import { usePathname } from "next/navigation"; | ||
import { Fullscreen, KeyRound, MessageSquare, Users } from "lucide-react"; | ||
|
||
import NavItem, { NavItemSkeleton } from "./nav-item"; | ||
|
||
const Navigation = () => { | ||
const pathname = usePathname(); | ||
const { user } = useUser(); | ||
|
||
const routes = [ | ||
{ | ||
label: "Stream", | ||
href: `/u/${user?.username}`, | ||
icon: Fullscreen, | ||
}, | ||
{ | ||
label: "Keys", | ||
href: `/u/${user?.username}/keys`, | ||
icon: KeyRound, | ||
}, | ||
{ | ||
label: "Chat", | ||
href: `/u/${user?.username}/chat`, | ||
icon: MessageSquare, | ||
}, | ||
{ | ||
label: "Community", | ||
href: `/u/${user?.username}/community`, | ||
icon: Users, | ||
}, | ||
]; | ||
|
||
if (!user?.username) { | ||
return ( | ||
<ul className="space-y-2"> | ||
{[...Array(4)].map((_, i) => ( | ||
<NavItemSkeleton key={i} /> | ||
))} | ||
</ul> | ||
); | ||
} | ||
|
||
return ( | ||
<ul className="space-y-2 px-2 pt-4 lg:pt-0"> | ||
{routes.map((route) => ( | ||
<NavItem | ||
key={route.href} | ||
label={route.label} | ||
icon={route.icon} | ||
href={route.href} | ||
isActive={pathname === route.href} | ||
/> | ||
))} | ||
</ul> | ||
); | ||
}; | ||
|
||
export default Navigation; |
57 changes: 57 additions & 0 deletions
57
app/(dashboard)/u/[username]/_components/sidebar/toggle.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
"use client"; | ||
|
||
import { ArrowLeftFromLine, ArrowRightFromLine } from "lucide-react"; | ||
|
||
import Hint from "@/components/hint"; | ||
import { Button } from "@/components/ui/button"; | ||
import { useCreatorSidebar } from "@/store/use-creator-sidebar"; | ||
|
||
const Toggle = () => { | ||
const { collapsed, onExpand, onCollapse } = useCreatorSidebar( | ||
(state) => state | ||
); | ||
|
||
const label = collapsed ? "Expand" : "Collapse"; | ||
|
||
return ( | ||
<> | ||
{collapsed && ( | ||
<div className="w-full hidden lg:flex items-center justify-center pt-4 mb-4"> | ||
<Hint | ||
label={label} | ||
side="right" | ||
asChild | ||
> | ||
<Button | ||
onClick={onExpand} | ||
variant="ghost" | ||
className="h-auto p-2" | ||
> | ||
<ArrowRightFromLine className="h-4 w-4" /> | ||
</Button> | ||
</Hint> | ||
</div> | ||
)} | ||
{!collapsed && ( | ||
<div className="p-3 pl-6 mb-2 hidden lg:flex items-center w-full"> | ||
<p className="font-semibold text-foreground">Dashboard</p> | ||
<Hint | ||
label={label} | ||
side="right" | ||
asChild | ||
> | ||
<Button | ||
onClick={onCollapse} | ||
variant="ghost" | ||
className="h-auto p-2 ml-auto" | ||
> | ||
<ArrowLeftFromLine className="h-4 w-4" /> | ||
</Button> | ||
</Hint> | ||
</div> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default Toggle; |
25 changes: 25 additions & 0 deletions
25
app/(dashboard)/u/[username]/_components/sidebar/wrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
"use client"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
import { useCreatorSidebar } from "@/store/use-creator-sidebar"; | ||
|
||
interface WrapperProps { | ||
children: React.ReactNode; | ||
} | ||
|
||
const Wrapper = ({ children }: WrapperProps) => { | ||
const { collapsed } = useCreatorSidebar((state) => state); | ||
|
||
return ( | ||
<aside | ||
className={cn( | ||
"fixed left-0 flex flex-col w-[70px] lg:w-60 h-full bg-secondary/40 z-50", | ||
collapsed && "lg:w-[70px]" | ||
)} | ||
> | ||
{children} | ||
</aside> | ||
); | ||
}; | ||
|
||
export default Wrapper; |
Oops, something went wrong.