chatbot-ui/components/ui/dashboard.tsx

139 lines
4.0 KiB
TypeScript

"use client"
import { Sidebar } from "@/components/sidebar/sidebar"
import { SidebarSwitcher } from "@/components/sidebar/sidebar-switcher"
import { Button } from "@/components/ui/button"
import { Tabs } from "@/components/ui/tabs"
import useHotkey from "@/lib/hooks/use-hotkey"
import { cn } from "@/lib/utils"
import { ContentType } from "@/types"
import { IconChevronCompactRight } from "@tabler/icons-react"
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { FC, useState } from "react"
import { useSelectFileHandler } from "../chat/chat-hooks/use-select-file-handler"
import { CommandK } from "../utility/command-k"
import { useTranslation } from 'react-i18next'
export const SIDEBAR_WIDTH = 350
interface DashboardProps {
children: React.ReactNode
}
export const Dashboard: FC<DashboardProps> = ({ children }) => {
const { t } = useTranslation()
useHotkey("s", () => setShowSidebar(prevState => !prevState))
const pathname = usePathname()
const router = useRouter()
const searchParams = useSearchParams()
const tabValue = searchParams.get("tab") || "chats"
const { handleSelectDeviceFile } = useSelectFileHandler()
const [contentType, setContentType] = useState<ContentType>(
tabValue as ContentType
)
const [showSidebar, setShowSidebar] = useState(
localStorage.getItem("showSidebar") === "true"
)
const [isDragging, setIsDragging] = useState(false)
const onFileDrop = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault()
const files = event.dataTransfer.files
const file = files[0]
handleSelectDeviceFile(file)
setIsDragging(false)
}
const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault()
setIsDragging(true)
}
const handleDragLeave = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault()
setIsDragging(false)
}
const onDragOver = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault()
}
const handleToggleSidebar = () => {
setShowSidebar(prevState => !prevState)
localStorage.setItem("showSidebar", String(!showSidebar))
}
return (
<div className="flex size-full">
<CommandK />
<div
className={cn(
"duration-200 dark:border-none " + (showSidebar ? "border-r-2" : "")
)}
style={{
// Sidebar
minWidth: showSidebar ? `${SIDEBAR_WIDTH}px` : "0px",
maxWidth: showSidebar ? `${SIDEBAR_WIDTH}px` : "0px",
width: showSidebar ? `${SIDEBAR_WIDTH}px` : "0px"
}}
>
{showSidebar && (
<Tabs
className="flex h-full"
value={contentType}
onValueChange={tabValue => {
setContentType(tabValue as ContentType)
router.replace(`${pathname}?tab=${tabValue}`)
}}
>
<SidebarSwitcher onContentTypeChange={setContentType} />
<Sidebar contentType={contentType} showSidebar={showSidebar} />
</Tabs>
)}
</div>
<div
className="bg-muted/50 relative flex w-screen min-w-[90%] grow flex-col sm:min-w-fit"
onDrop={onFileDrop}
onDragOver={onDragOver}
onDragEnter={handleDragEnter}
onDragLeave={handleDragLeave}
>
{isDragging ? (
<div className="flex h-full items-center justify-center bg-black/50 text-2xl text-white">
{t("side.dropFileHere")}
</div>
) : (
children
)}
<Button
className={cn(
"absolute left-[4px] top-[50%] z-10 size-[32px] cursor-pointer"
)}
style={{
// marginLeft: showSidebar ? `${SIDEBAR_WIDTH}px` : "0px",
transform: showSidebar ? "rotate(180deg)" : "rotate(0deg)"
}}
variant="ghost"
size="icon"
onClick={handleToggleSidebar}
>
<IconChevronCompactRight size={24} />
</Button>
</div>
</div>
)
}