api-info-panel.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { useState, useCallback } from 'react'
  2. import { Route } from 'lucide-react'
  3. import { useTranslation } from 'react-i18next'
  4. import { ScrollArea } from '@/components/ui/scroll-area'
  5. import { useApiInfo } from '@/features/dashboard/hooks/use-status-data'
  6. import {
  7. testUrlLatency,
  8. getDefaultPingStatus,
  9. } from '@/features/dashboard/lib/api-info'
  10. import type { PingStatusMap, ApiInfoItem } from '@/features/dashboard/types'
  11. import { PanelWrapper } from '../ui/panel-wrapper'
  12. import { ApiInfoItemComponent } from './api-info-item'
  13. export function ApiInfoPanel() {
  14. const { t } = useTranslation()
  15. const { items: list, loading } = useApiInfo()
  16. const [pingStatus, setPingStatus] = useState<PingStatusMap>({})
  17. const handleTest = useCallback(async (url: string) => {
  18. setPingStatus((prev) => ({
  19. ...prev,
  20. [url]: { latency: null, testing: true, error: false },
  21. }))
  22. const result = await testUrlLatency(url)
  23. setPingStatus((prev) => ({ ...prev, [url]: result }))
  24. }, [])
  25. return (
  26. <PanelWrapper
  27. title={
  28. <span className='flex items-center gap-2'>
  29. <Route className='text-muted-foreground/60 size-4' />
  30. {t('API Info')}
  31. </span>
  32. }
  33. description={t('Configured routes and latency checks')}
  34. loading={loading}
  35. empty={!list.length}
  36. emptyMessage={t('No API routes configured')}
  37. height='h-72'
  38. contentClassName='p-0'
  39. >
  40. <ScrollArea className='h-72'>
  41. <div>
  42. {list.map((item: ApiInfoItem, idx: number) => (
  43. <div
  44. key={item.url}
  45. className={
  46. idx < list.length - 1 ? 'border-border/60 border-b' : ''
  47. }
  48. >
  49. <ApiInfoItemComponent
  50. item={item}
  51. status={pingStatus[item.url] || getDefaultPingStatus()}
  52. onTest={handleTest}
  53. />
  54. </div>
  55. ))}
  56. </div>
  57. </ScrollArea>
  58. </PanelWrapper>
  59. )
  60. }