added button themes and fixed alignment
This commit is contained in:
parent
52dd723bba
commit
baaf624eae
4 changed files with 139 additions and 52 deletions
|
|
@ -1,7 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useGetConversationsQuery, type ChatConversation } from "@/app/api/queries/useGetConversationsQuery";
|
||||
import {
|
||||
useGetConversationsQuery,
|
||||
type ChatConversation,
|
||||
} from "@/app/api/queries/useGetConversationsQuery";
|
||||
import { KnowledgeFilterDropdown } from "@/components/knowledge-filter-dropdown";
|
||||
import { ModeToggle } from "@/components/mode-toggle";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
import { Bell, Loader2 } from "lucide-react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useGetConversationsQuery, type ChatConversation } from "@/app/api/queries/useGetConversationsQuery";
|
||||
import {
|
||||
useGetConversationsQuery,
|
||||
type ChatConversation,
|
||||
} from "@/app/api/queries/useGetConversationsQuery";
|
||||
import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery";
|
||||
import { KnowledgeFilterPanel } from "@/components/knowledge-filter-panel";
|
||||
import Logo from "@/components/logo/logo";
|
||||
|
|
@ -50,10 +53,10 @@ export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
|||
|
||||
// Calculate active tasks for the bell icon
|
||||
const activeTasks = tasks.filter(
|
||||
(task) =>
|
||||
task =>
|
||||
task.status === "pending" ||
|
||||
task.status === "running" ||
|
||||
task.status === "processing",
|
||||
task.status === "processing"
|
||||
);
|
||||
|
||||
// Show loading state when backend isn't ready
|
||||
|
|
@ -85,7 +88,7 @@ export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
|||
</div>
|
||||
</div>
|
||||
<div className="header-end-division">
|
||||
<div className="header-end-display">
|
||||
<div className="justify-end flex items-center">
|
||||
{/* Knowledge Filter Dropdown */}
|
||||
{/* <KnowledgeFilterDropdown
|
||||
selectedFilter={selectedFilter}
|
||||
|
|
@ -99,20 +102,18 @@ export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
|||
{/* <DiscordLink inviteCode="EqksyE2EX9" /> */}
|
||||
|
||||
{/* Task Notification Bell */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="iconSm"
|
||||
<button
|
||||
onClick={toggleMenu}
|
||||
className="relative"
|
||||
className="h-9 w-9 hover:bg-muted rounded-lg flex items-center justify-center"
|
||||
>
|
||||
<Bell className="h-4 w-4 text-muted-foreground" />
|
||||
<Bell size={20} className="text-muted-foreground" />
|
||||
{activeTasks.length > 0 && (
|
||||
<div className="header-notifications" />
|
||||
)}
|
||||
</Button>
|
||||
</button>
|
||||
|
||||
{/* Separator */}
|
||||
<div className="w-px h-6 bg-border" />
|
||||
<div className="w-px h-6 bg-border ml-3 mr-4" />
|
||||
|
||||
<UserNav />
|
||||
</div>
|
||||
|
|
|
|||
68
frontend/src/components/ui/buttonTheme.tsx
Normal file
68
frontend/src/components/ui/buttonTheme.tsx
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { Monitor, Moon, Sun } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
export const ThemeButtons = () => {
|
||||
const { theme, setTheme } = useTheme();
|
||||
const [selectedTheme, setSelectedTheme] = useState("dark");
|
||||
|
||||
// Sync local state with theme context
|
||||
useEffect(() => {
|
||||
if (theme) {
|
||||
setSelectedTheme(theme);
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
const handleThemeChange = (newTheme: string) => {
|
||||
setSelectedTheme(newTheme);
|
||||
setTheme(newTheme);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 border border-border rounded-full">
|
||||
{/* Light Theme Button */}
|
||||
<button
|
||||
className={`h-7 w-7 rounded-full flex items-center justify-center ${
|
||||
selectedTheme === "light"
|
||||
? "bg-amber-400 text-primary"
|
||||
: "text-foreground hover:bg-amber-400 hover:text-background"
|
||||
}`}
|
||||
onClick={() => handleThemeChange("light")}
|
||||
data-testid="menu_light_button"
|
||||
id="menu_light_button"
|
||||
>
|
||||
<Sun className="h-4 w-4 rounded-full" />
|
||||
</button>
|
||||
|
||||
{/* Dark Theme Button */}
|
||||
<button
|
||||
className={`h-7 w-7 rounded-full flex items-center justify-center ${
|
||||
selectedTheme === "dark"
|
||||
? "bg-purple-500/20 text-purple-500 hover:bg-purple-500/20 hover:text-purple-500"
|
||||
: "text-foreground hover:bg-purple-500/20 hover:text-purple-500"
|
||||
}`}
|
||||
onClick={() => handleThemeChange("dark")}
|
||||
data-testid="menu_dark_button"
|
||||
id="menu_dark_button"
|
||||
>
|
||||
<Moon className="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
{/* System Theme Button */}
|
||||
<button
|
||||
className={`h-7 w-7 rounded-full flex items-center justify-center ${
|
||||
selectedTheme === "system"
|
||||
? "bg-foreground text-background"
|
||||
: "hover:bg-foreground hover:text-background"
|
||||
}`}
|
||||
onClick={() => handleThemeChange("system")}
|
||||
data-testid="menu_system_button"
|
||||
id="menu_system_button"
|
||||
>
|
||||
<Monitor className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThemeButtons;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
"use client"
|
||||
"use client";
|
||||
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
|
|
@ -9,65 +9,79 @@ import {
|
|||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { useAuth } from "@/contexts/auth-context"
|
||||
import { LogIn, LogOut, User, Moon, Sun, ChevronsUpDown } from "lucide-react"
|
||||
import { useTheme } from "next-themes"
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { useAuth } from "@/contexts/auth-context";
|
||||
import { LogIn, LogOut, User, Moon, Sun, ChevronsUpDown } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
import ThemeButtons from "./ui/buttonTheme";
|
||||
|
||||
export function UserNav() {
|
||||
const { user, isLoading, isAuthenticated, isNoAuthMode, login, logout } = useAuth()
|
||||
const { theme, setTheme } = useTheme()
|
||||
const { user, isLoading, isAuthenticated, isNoAuthMode, login, logout } =
|
||||
useAuth();
|
||||
const { theme, setTheme } = useTheme();
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="h-8 w-8 rounded-full bg-muted animate-pulse" />
|
||||
)
|
||||
return <div className="h-8 w-8 rounded-full bg-muted animate-pulse" />;
|
||||
}
|
||||
|
||||
// In no-auth mode, show a simple theme switcher instead of auth UI
|
||||
if (isNoAuthMode) {
|
||||
return (
|
||||
<Button
|
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
||||
variant="outline"
|
||||
<Button
|
||||
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
{theme === 'dark' ? <Sun className="h-4 w-4" /> : <Moon className="h-4 w-4" />}
|
||||
{theme === "dark" ? (
|
||||
<Sun className="h-4 w-4" />
|
||||
) : (
|
||||
<Moon className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
<Button
|
||||
onClick={login}
|
||||
variant="outline"
|
||||
<Button
|
||||
onClick={login}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<LogIn className="h-4 w-4" />
|
||||
Sign In
|
||||
</Button>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="flex items-center gap-1 h-8 px-1 rounded-full">
|
||||
<Avatar className="h-6 w-6">
|
||||
<AvatarImage src={user?.picture} alt={user?.name} />
|
||||
<AvatarFallback className="text-xs">
|
||||
{user?.name ? user.name.charAt(0).toUpperCase() : <User className="h-3 w-3" />}
|
||||
<button className="hover:bg-muted rounded-lg flex items-center justify-center">
|
||||
<Avatar className="rounded-md w-8 h-8">
|
||||
<AvatarImage
|
||||
width={16}
|
||||
height={16}
|
||||
src={user?.picture}
|
||||
alt={user?.name}
|
||||
className="rounded-md"
|
||||
/>
|
||||
<AvatarFallback className="text-xs rounded-md">
|
||||
{user?.name ? (
|
||||
user.name.charAt(0).toUpperCase()
|
||||
) : (
|
||||
<User className="h-3 w-3" />
|
||||
)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<ChevronsUpDown className="h-3 w-3 text-muted-foreground" />
|
||||
</Button>
|
||||
<ChevronsUpDown size={16} className="text-muted-foreground mx-2" />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56" align="end" forceMount>
|
||||
<DropdownMenuLabel className="font-normal">
|
||||
<div className="flex flex-col space-y-1">
|
||||
<div className="flex flex-col space-y-2">
|
||||
<p className="text-sm font-medium leading-none">{user?.name}</p>
|
||||
<p className="text-xs leading-none text-muted-foreground">
|
||||
{user?.email}
|
||||
|
|
@ -75,20 +89,21 @@ export function UserNav() {
|
|||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
|
||||
{theme === "light" ? (
|
||||
<Moon className="mr-2 h-4 w-4" />
|
||||
) : (
|
||||
<Sun className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
<span>Toggle Theme</span>
|
||||
</DropdownMenuItem>
|
||||
{/* <DropdownMenuItem className="flex items-center justify-between"> */}
|
||||
<div className="flex items-center justify-between px-2 h-8">
|
||||
<span className="text-sm">Theme</span>
|
||||
<ThemeButtons />
|
||||
</div>
|
||||
{/* </DropdownMenuItem> */}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={logout} className="text-red-600 focus:text-red-600">
|
||||
<DropdownMenuItem
|
||||
onClick={logout}
|
||||
className="text-red-600 focus:text-red-600"
|
||||
>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
<span>Log out</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue