Download vetcopilot-app/src/hooks/useOfflineCache.ts from WWsCa/VetNet-LCPS: direct link, hf CLI and curl.
- Browser
- Download file 3.78 kB
-
https://huggingface.co/WWsCa/VetNet-LCPS/resolve/main/vetcopilot-app/src/hooks/useOfflineCache.ts
- Command line
-
hf download hf://WWsCa/VetNet-LCPS/vetcopilot-app/src/hooks/useOfflineCache.ts
-
curl -L -o useOfflineCache.ts https://huggingface.co/WWsCa/VetNet-LCPS/resolve/main/vetcopilot-app/src/hooks/useOfflineCache.ts
3.78 kB
| /** | |
| * useOfflineCache Hook | |
| * | |
| * React hook providing a reactive interface to the IndexedDB-backed | |
| * offline SOAP consultation cache. | |
| * | |
| * Exposes the full cached consultation list, individual lookup, | |
| * cache/remove operations, and online/offline status. | |
| */ | |
| import { useState, useEffect, useCallback, useRef } from 'react' | |
| import type { CachedConsultation } from '../utils/offlineCache' | |
| import * as offlineCache from '../utils/offlineCache' | |
| // ================================================================ | |
| // Hook return type | |
| // ================================================================ | |
| export interface UseOfflineCacheReturn { | |
| /** All cached consultations, newest first */ | |
| cachedConsultations: CachedConsultation[] | |
| /** True while the initial load from IndexedDB is in progress */ | |
| isLoading: boolean | |
| /** Cache a consultation record (also refreshes the list) */ | |
| cacheConsultation: (data: CachedConsultation) => Promise<void> | |
| /** Look up a single cached consultation by ID */ | |
| getConsultation: (id: string) => Promise<CachedConsultation | null> | |
| /** Remove a single cached consultation by ID */ | |
| removeConsultation: (id: string) => Promise<void> | |
| /** Whether the browser is currently offline */ | |
| isOffline: boolean | |
| } | |
| // ================================================================ | |
| // Hook implementation | |
| // ================================================================ | |
| export function useOfflineCache(): UseOfflineCacheReturn { | |
| const [cachedConsultations, setCachedConsultations] = useState<CachedConsultation[]>([]) | |
| const [isLoading, setIsLoading] = useState(true) | |
| const [isOffline, setIsOffline] = useState(!navigator.onLine) | |
| // Track mount state to prevent state updates after unmount | |
| const mountedRef = useRef(true) | |
| // ----- Load all cached consultations on mount ----- | |
| const refreshList = useCallback(async () => { | |
| try { | |
| const items = await offlineCache.getAllCachedConsultations() | |
| if (mountedRef.current) { | |
| setCachedConsultations(items) | |
| } | |
| } catch { | |
| // Silently ignore — cache reads failing shouldn't break the UI | |
| } | |
| }, []) | |
| useEffect(() => { | |
| mountedRef.current = true | |
| const load = async () => { | |
| setIsLoading(true) | |
| await refreshList() | |
| if (mountedRef.current) { | |
| setIsLoading(false) | |
| } | |
| } | |
| load() | |
| return () => { | |
| mountedRef.current = false | |
| } | |
| }, [refreshList]) | |
| // ----- Online/offline detection ----- | |
| useEffect(() => { | |
| const handleOnline = () => { | |
| if (mountedRef.current) { | |
| setIsOffline(false) | |
| } | |
| } | |
| const handleOffline = () => { | |
| if (mountedRef.current) { | |
| setIsOffline(true) | |
| } | |
| } | |
| window.addEventListener('online', handleOnline) | |
| window.addEventListener('offline', handleOffline) | |
| return () => { | |
| window.removeEventListener('online', handleOnline) | |
| window.removeEventListener('offline', handleOffline) | |
| } | |
| }, []) | |
| // ----- Cache a consultation ----- | |
| const cacheConsultation = useCallback( | |
| async (data: CachedConsultation) => { | |
| await offlineCache.cacheConsultation(data) | |
| await refreshList() | |
| }, | |
| [refreshList], | |
| ) | |
| // ----- Look up a single consultation ----- | |
| const getConsultation = useCallback( | |
| async (id: string): Promise<CachedConsultation | null> => { | |
| return offlineCache.getCachedConsultation(id) | |
| }, | |
| [], | |
| ) | |
| // ----- Remove a single consultation ----- | |
| const removeConsultation = useCallback( | |
| async (id: string) => { | |
| await offlineCache.removeConsultation(id) | |
| await refreshList() | |
| }, | |
| [refreshList], | |
| ) | |
| return { | |
| cachedConsultations, | |
| isLoading, | |
| cacheConsultation, | |
| getConsultation, | |
| removeConsultation, | |
| isOffline, | |
| } | |
| } | |