1- import { useQuery } from '@tanstack/react-query'
2- import { Loader2 , Sparkles } from 'lucide-react'
31import type { CSSProperties , PropsWithChildren } from 'react'
42import { useEffect , useState } from 'react'
53import { useLocation , useNavigate } from 'react-router'
@@ -20,7 +18,6 @@ import {
2018} from '~/ui/layout/sidebar-layout'
2119import { cn } from '~/utils/cn'
2220
23- import { AITaskStatus , getTasks } from './api/tasks'
2421import { useI18n } from './i18n'
2522
2623export function AdminShell ( props : PropsWithChildren ) {
@@ -37,34 +34,6 @@ export function AdminShell(props: PropsWithChildren) {
3734 const id = requestAnimationFrame ( ( ) => setSidebarTransitionsEnabled ( true ) )
3835 return ( ) => cancelAnimationFrame ( id )
3936 } , [ ] )
40- const pendingAiTasksQuery = useQuery ( {
41- queryFn : ( ) =>
42- getTasks ( {
43- page : 1 ,
44- scope : 'ai' ,
45- size : 1 ,
46- status : AITaskStatus . Pending ,
47- } ) ,
48- queryKey : [ 'shell' , 'ai-tasks' , AITaskStatus . Pending ] ,
49- refetchInterval : 5000 ,
50- } )
51- const runningAiTasksQuery = useQuery ( {
52- queryFn : ( ) =>
53- getTasks ( {
54- page : 1 ,
55- scope : 'ai' ,
56- size : 1 ,
57- status : AITaskStatus . Running ,
58- } ) ,
59- queryKey : [ 'shell' , 'ai-tasks' , AITaskStatus . Running ] ,
60- refetchInterval : 5000 ,
61- } )
62- const activeAiTaskCount =
63- ( pendingAiTasksQuery . data ?. total ?? 0 ) +
64- ( runningAiTasksQuery . data ?. total ?? 0 )
65- const isFetchingAiTaskCount =
66- pendingAiTasksQuery . isFetching || runningAiTasksQuery . isFetching
67-
6837 // Sidebar HJKL / arrow-key navigation. One binding is enough — the hook
6938 // looks up the scope's DOM element at fire time, so whichever sidebar
7039 // (desktop aside or mobile Drawer) is currently mounted handles the keys.
@@ -135,17 +104,6 @@ export function AdminShell(props: PropsWithChildren) {
135104 < section className = "relative flex h-screen min-h-0 min-w-0 flex-col bg-background" >
136105 < div className = "relative min-h-0 flex-1 overflow-hidden" >
137106 { props . children }
138- { activeAiTaskCount > 0 ? (
139- < AiTaskFloatingButton
140- activeCount = { activeAiTaskCount }
141- fetching = { isFetchingAiTaskCount }
142- onClick = { ( ) => navigate ( '/tasks?scope=ai' ) }
143- title = { t ( 'shell.aiTask.title' ) }
144- ariaLabel = { t ( 'shell.aiTask.ariaLabel' , {
145- count : activeAiTaskCount ,
146- } ) }
147- />
148- ) : null }
149107 </ div >
150108 </ section >
151109
@@ -180,35 +138,3 @@ function toggleFocusedNavItem(event: KeyboardEvent) {
180138 event . preventDefault ( )
181139 useSidebarExpandStore . getState ( ) . toggle ( path )
182140}
183-
184- function AiTaskFloatingButton ( props : {
185- activeCount : number
186- fetching : boolean
187- onClick : ( ) => void
188- title : string
189- ariaLabel : string
190- } ) {
191- return (
192- < button
193- aria-label = { props . ariaLabel }
194- className = "outline-hidden absolute bottom-4 right-4 z-30 inline-flex h-10 items-center gap-2 rounded-full border border-neutral-950 bg-neutral-950 px-3 text-sm font-medium text-white shadow-lg transition-all hover:bg-neutral-800 focus-visible:ring-2 focus-visible:ring-[var(--color-primary-shallow)] dark:border-neutral-100 dark:bg-neutral-100 dark:text-neutral-950 dark:hover:bg-neutral-200"
195- onClick = { props . onClick }
196- title = { props . title }
197- type = "button"
198- >
199- < span className = "relative inline-flex size-4 items-center justify-center" >
200- < Sparkles aria-hidden = "true" className = "size-4" />
201- { props . fetching ? (
202- < Loader2
203- aria-hidden = "true"
204- className = "absolute -right-1 -top-1 size-2.5 animate-spin"
205- />
206- ) : null }
207- </ span >
208- < span > { props . title } </ span >
209- < span className = "inline-flex min-w-5 items-center justify-center rounded-full bg-white px-1.5 text-xs font-semibold tabular-nums text-neutral-950 dark:bg-neutral-950 dark:text-white" >
210- { props . activeCount > 99 ? '99+' : props . activeCount }
211- </ span >
212- </ button >
213- )
214- }
0 commit comments