Sessions.tsxā¢4.88 kB
'use client'
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useQueryState } from 'nuqs'
import { useStore } from '@/store'
import useSessionLoader from '@/hooks/useSessionLoader'
import SessionItem from './SessionItem'
import SessionBlankState from './SessionBlankState'
import { Skeleton } from '@/components/ui/skeleton'
import { cn } from '@/lib/utils'
interface SkeletonListProps {
skeletonCount: number
}
const SkeletonList: FC<SkeletonListProps> = ({ skeletonCount }) => {
const list = useMemo(
() => Array.from({ length: skeletonCount }, (_, i) => i),
[skeletonCount]
)
return list.map((k, idx) => (
<Skeleton
key={k}
className={cn(
'mb-1 h-11 rounded-lg px-3 py-2',
idx > 0 && 'bg-background-secondary'
)}
/>
))
}
const Sessions = () => {
const [agentId] = useQueryState('agent', {
parse: (v) => v || undefined,
history: 'push'
})
const [teamId] = useQueryState('team')
const [sessionId] = useQueryState('session')
const [dbId] = useQueryState('db_id')
const {
selectedEndpoint,
mode,
isEndpointActive,
isEndpointLoading,
hydrated,
sessionsData,
setSessionsData,
isSessionsLoading
} = useStore()
console.log({ sessionsData })
const [isScrolling, setIsScrolling] = useState(false)
const [selectedSessionId, setSelectedSessionId] = useState<string | null>(
null
)
const { getSessions, getSession } = useSessionLoader()
const scrollTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null)
const handleScroll = () => {
setIsScrolling(true)
if (scrollTimeoutRef.current) {
clearTimeout(scrollTimeoutRef.current)
}
scrollTimeoutRef.current = setTimeout(() => {
setIsScrolling(false)
}, 1500)
}
// Cleanup the scroll timeout when component unmounts
useEffect(() => {
return () => {
if (scrollTimeoutRef.current) {
clearTimeout(scrollTimeoutRef.current)
}
}
}, [])
useEffect(() => {
if (hydrated && sessionId && selectedEndpoint && (agentId || teamId)) {
const entityType = agentId ? 'agent' : 'team'
getSession({ entityType, agentId, teamId, dbId }, sessionId)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hydrated, sessionId, selectedEndpoint, agentId, teamId, dbId])
useEffect(() => {
if (!selectedEndpoint || isEndpointLoading) return
if (!(agentId || teamId || dbId)) {
setSessionsData([])
return
}
setSessionsData([])
getSessions({
entityType: mode,
agentId,
teamId,
dbId
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
selectedEndpoint,
agentId,
teamId,
mode,
isEndpointLoading,
getSessions,
dbId
])
useEffect(() => {
if (sessionId) setSelectedSessionId(sessionId)
}, [sessionId])
const handleSessionClick = useCallback(
(id: string) => () => setSelectedSessionId(id),
[]
)
if (isSessionsLoading || isEndpointLoading) {
return (
<div className="w-full">
<div className="mb-2 text-xs font-medium uppercase">Sessions</div>
<div className="mt-4 h-[calc(100vh-325px)] w-full overflow-y-auto">
<SkeletonList skeletonCount={5} />
</div>
</div>
)
}
return (
<div className="w-full">
<div className="mb-2 w-full text-xs font-medium uppercase">Sessions</div>
<div
className={`h-[calc(100vh-345px)] overflow-y-auto font-geist transition-all duration-300 [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar]:transition-opacity [&::-webkit-scrollbar]:duration-300 ${
isScrolling
? '[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-background [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar]:opacity-0'
: '[&::-webkit-scrollbar]:opacity-100'
}`}
onScroll={handleScroll}
onMouseOver={() => setIsScrolling(true)}
onMouseLeave={handleScroll}
>
{!isEndpointActive ||
(!isSessionsLoading &&
(!sessionsData || sessionsData?.length === 0)) ? (
<SessionBlankState />
) : (
<div className="flex flex-col gap-y-1 pr-1">
{sessionsData?.map((entry, idx) => (
<SessionItem
key={`${entry?.session_id}-${idx}`}
currentSessionId={selectedSessionId}
isSelected={selectedSessionId === entry?.session_id}
onSessionClick={handleSessionClick(entry?.session_id)}
session_name={entry?.session_name ?? '-'}
session_id={entry?.session_id}
created_at={entry?.created_at}
/>
))}
</div>
)}
</div>
</div>
)
}
export default Sessions