mirror of
https://github.com/Dvorinka/Trackeep.git
synced 2026-07-29 22:13:51 +00:00
uppdate
This commit is contained in:
@@ -164,16 +164,11 @@ export function AIChatPanel(props: AIChatPanelProps) {
|
||||
onClick={() => setShowModelPicker(!showModelPicker())}
|
||||
class="flex items-center gap-2 px-3 py-1.5 bg-muted hover:bg-muted/80 rounded-full text-xs transition-colors"
|
||||
>
|
||||
<Show when={aiModels.find(m => m.id === selectedModel())?.iconId}>
|
||||
<AIProviderIcon
|
||||
providerId={aiModels.find(m => m.id === selectedModel())?.iconId || 'longcat'}
|
||||
size="1rem"
|
||||
class="rounded-full"
|
||||
/>
|
||||
</Show>
|
||||
<Show when={!aiModels.find(m => m.id === selectedModel())?.iconId}>
|
||||
<div class="w-4 h-4 rounded-full bg-gradient-to-r from-blue-500 to-purple-500"></div>
|
||||
</Show>
|
||||
<AIProviderIcon
|
||||
providerId={aiModels.find(m => m.id === selectedModel())?.iconId || 'longcat'}
|
||||
size="1rem"
|
||||
class="rounded-full"
|
||||
/>
|
||||
<span class="text-muted-foreground">
|
||||
{aiModels.find(m => m.id === selectedModel())?.name?.split(' ')[0] || 'AI'}
|
||||
</span>
|
||||
@@ -196,20 +191,11 @@ export function AIChatPanel(props: AIChatPanelProps) {
|
||||
}`}
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<Show when={model.iconId}>
|
||||
<AIProviderIcon
|
||||
providerId={model.iconId!}
|
||||
size="0.75rem"
|
||||
class="rounded-full flex-shrink-0"
|
||||
/>
|
||||
</Show>
|
||||
<Show when={!model.iconId}>
|
||||
<div class={`w-3 h-3 rounded-full flex-shrink-0 ${
|
||||
model.provider === 'LongCat' ? 'bg-gradient-to-r from-orange-500 to-red-500' :
|
||||
model.provider === 'OpenAI' ? 'bg-gradient-to-r from-green-500 to-emerald-500' :
|
||||
'bg-gradient-to-r from-purple-500 to-pink-500'
|
||||
}`}></div>
|
||||
</Show>
|
||||
<AIProviderIcon
|
||||
providerId={model.iconId!}
|
||||
size="0.75rem"
|
||||
class="rounded-full flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-medium truncate">{model.name}</div>
|
||||
<div class="text-muted-foreground text-xs truncate">{model.description}</div>
|
||||
@@ -224,7 +210,7 @@ export function AIChatPanel(props: AIChatPanelProps) {
|
||||
|
||||
<div class="flex items-center gap-3 text-xs text-muted-foreground">
|
||||
<span>{aiModels.find(m => m.id === selectedModel())?.provider || 'LongCat'}</span>
|
||||
<a href="/app/settings" class="text-primary hover:underline">
|
||||
<a href="/app/settings#ai" class="text-primary hover:underline">
|
||||
AI settings
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -79,7 +79,7 @@ export function FloatingAI(props: FloatingAIProps) {
|
||||
|
||||
{/* AI Chat Modal */}
|
||||
<Show when={props.isChatOpen}>
|
||||
<div class="fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4">
|
||||
<div class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 mt-0 p-4">
|
||||
<div class="bg-card border border-border rounded-lg shadow-xl max-w-md w-full max-h-[600px] flex flex-col" style="width: 420px;">
|
||||
{/* Header */}
|
||||
<div class="flex items-center justify-between p-4 border-b border-border bg-gradient-to-r from-primary/10 to-primary/5">
|
||||
|
||||
@@ -15,9 +15,10 @@ import { useAuth } from '@/lib/auth'
|
||||
export interface HeaderProps {
|
||||
class?: string
|
||||
title?: string
|
||||
onMenuClick?: () => void
|
||||
}
|
||||
|
||||
export function Header(_props: HeaderProps) {
|
||||
export function Header(props: HeaderProps) {
|
||||
const [showUploadModal, setShowUploadModal] = createSignal(false);
|
||||
const { authState, updateProfile } = useAuth();
|
||||
|
||||
@@ -55,8 +56,15 @@ export function Header(_props: HeaderProps) {
|
||||
<div class="flex justify-between px-6 pt-4 pb-4">
|
||||
{/* Left side */}
|
||||
<div class="flex items-center">
|
||||
{/* Mobile menu button */}
|
||||
<button type="button" aria-haspopup="dialog" aria-expanded="false" data-closed="" class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-shadow focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-inherit hover:bg-accent/50 hover:text-accent-foreground h-9 w-9 md:hidden mr-2">
|
||||
{/* Menu button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={props.onMenuClick}
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded="false"
|
||||
data-closed=""
|
||||
class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-shadow focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-inherit hover:bg-accent/50 hover:text-accent-foreground h-9 w-9 mr-2"
|
||||
>
|
||||
<IconMenu2 class="size-6" />
|
||||
</button>
|
||||
|
||||
@@ -79,10 +87,10 @@ export function Header(_props: HeaderProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowUploadModal(true)}
|
||||
class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-shadow focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-9 px-4 py-2"
|
||||
class="inline-flex items-center justify-center rounded-md text-sm font-medium transition-shadow focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-10 px-4 py-2 text-base"
|
||||
>
|
||||
<IconUpload class="size-4" />
|
||||
<span class="hidden sm:inline ml-2">Import a document</span>
|
||||
<IconUpload class="size-4 mr-2" />
|
||||
Import a document
|
||||
</button>
|
||||
|
||||
{/* Color switcher dropdown */}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { children, createSignal, onMount } from 'solid-js'
|
||||
import { Sidebar } from './Sidebar'
|
||||
import { Header } from './Header'
|
||||
import { AIChatPanel } from './AIChatPanel'
|
||||
import { UpdateNotification } from '../ui/UpdateNotification'
|
||||
import { IconBrain } from '@tabler/icons-solidjs'
|
||||
|
||||
export interface LayoutProps {
|
||||
@@ -15,6 +14,7 @@ export interface LayoutProps {
|
||||
export function Layout(props: LayoutProps) {
|
||||
const resolved = children(() => props.children)
|
||||
const [isChatOpen, setIsChatOpen] = createSignal(false)
|
||||
const [isSidebarOpen, setIsSidebarOpen] = createSignal(false)
|
||||
|
||||
onMount(() => {
|
||||
// Initialize dark mode from localStorage or system preference
|
||||
@@ -142,19 +142,33 @@ export function Layout(props: LayoutProps) {
|
||||
setIsChatOpen(!isChatOpen())
|
||||
}
|
||||
|
||||
const toggleSidebar = () => {
|
||||
setIsSidebarOpen(!isSidebarOpen())
|
||||
}
|
||||
|
||||
const closeSidebar = () => {
|
||||
setIsSidebarOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="min-h-screen font-sans text-sm font-400 bg-background text-foreground">
|
||||
{/* Update Notification - Above everything */}
|
||||
<UpdateNotification />
|
||||
|
||||
<div class="flex flex-row h-screen min-h-0">
|
||||
<div class="flex flex-row h-screen min-h-0 relative">
|
||||
{/* Mobile Sidebar Overlay */}
|
||||
{isSidebarOpen() && (
|
||||
<div
|
||||
class="fixed inset-0 bg-black/50 z-40"
|
||||
onClick={closeSidebar}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Sidebar */}
|
||||
<Sidebar />
|
||||
<Sidebar isOpen={isSidebarOpen()} onClose={closeSidebar} />
|
||||
|
||||
{/* Main Content */}
|
||||
<div class="flex-1 min-h-0 flex flex-col">
|
||||
{/* Header */}
|
||||
<Header title={props.title} />
|
||||
<Header title={props.title} onMenuClick={toggleSidebar} />
|
||||
|
||||
{/* Page Content */}
|
||||
<main class="flex-1 overflow-auto max-w-screen">
|
||||
|
||||
@@ -20,7 +20,8 @@ import {
|
||||
IconCalendar,
|
||||
IconLogout,
|
||||
IconBuilding,
|
||||
IconPlus
|
||||
IconPlus,
|
||||
IconX
|
||||
} from '@tabler/icons-solidjs'
|
||||
import { UpdateChecker } from '../ui/UpdateChecker'
|
||||
|
||||
@@ -48,9 +49,11 @@ const mockWorkspaces = [
|
||||
|
||||
export interface SidebarProps {
|
||||
class?: string
|
||||
isOpen?: boolean
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
export function Sidebar(_props: SidebarProps) {
|
||||
export function Sidebar(props: SidebarProps) {
|
||||
const location = useLocation()
|
||||
const [isWorkspaceDropdownOpen, setIsWorkspaceDropdownOpen] = createSignal(false)
|
||||
const [selectedWorkspace, setSelectedWorkspace] = createSignal(mockWorkspaces[0])
|
||||
@@ -84,10 +87,23 @@ export function Sidebar(_props: SidebarProps) {
|
||||
})
|
||||
|
||||
return (
|
||||
<div class="w-280px border-r border-r-border flex-shrink-0 hidden md:block bg-card">
|
||||
<div class="flex h-full">
|
||||
<div class="h-full flex flex-col pb-6 flex-1 min-w-0">
|
||||
{/* Organization Selector */}
|
||||
<>
|
||||
{/* Mobile Close Button - Above sidebar */}
|
||||
<Show when={props.isOpen}>
|
||||
<button
|
||||
onClick={props.onClose}
|
||||
class="fixed top-4 right-4 z-50 md:hidden inline-flex items-center justify-center rounded-md text-sm font-medium transition-shadow focus-visible:outline-none focus-visible:ring-1.5 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-inherit hover:bg-accent/50 hover:text-accent-foreground h-8 w-8"
|
||||
>
|
||||
<IconX class="size-4" />
|
||||
</button>
|
||||
</Show>
|
||||
|
||||
<div class={`fixed inset-y-0 left-0 z-50 w-280px border-r border-r-border flex-shrink-0 bg-card transform transition-transform duration-300 ease-in-out md:relative md:translate-x-0 ${
|
||||
props.isOpen ? 'translate-x-0' : '-translate-x-full'
|
||||
}`}>
|
||||
<div class="flex h-full">
|
||||
<div class="h-full flex flex-col pb-6 flex-1 min-w-0">
|
||||
{/* Organization Selector */}
|
||||
<div class="p-4 pb-0 min-w-0 max-w-full" id="workspace-selector">
|
||||
<div role="group" class="w-full relative">
|
||||
<button
|
||||
@@ -261,5 +277,6 @@ export function Sidebar(_props: SidebarProps) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user