Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 'use client'; import { useCallback, useMemo, useState } from 'react'; import { Availability } from '@/types/service/user'; type AvailabilityState = | { status: 'idle' } | { status: 'checking' } | { status: 'available'; message: string } | { status: 'unavailable'; message: string } | { status: 'error'; message: string }; type Messages = { available: string; unavailable: string; error: string; checking: string; }; export const useAvailabilityCheck = <TQuery>( request: (query: TQuery) => Promise<Availability>, buildQuery: (value: string) => TQuery, messages: Messages, ) => { const [state, setState] = useState<AvailabilityState>({ status: 'idle' }); const hint = useMemo(() => { if (state.status === 'checking') return messages.checking; if (state.status === 'available') return state.message; if (state.status === 'unavailable') return state.message; if (state.status === 'error') return state.message; return undefined; }, [messages.checking, state]); const isChecking = state.status === 'checking'; const isAvailable = state.status === 'available'; const reset = useCallback(() => { setState({ status: 'idle' }); }, []); const check = useCallback( async (value: string) => { const trimmed = value.trim(); if (!trimmed) return; if (isChecking) return; try { setState({ status: 'checking' }); const data = await request(buildQuery(trimmed)); const available = Boolean(data.available); if (available) { setState({ status: 'available', message: messages.available }); } else { setState({ status: 'unavailable', message: messages.unavailable }); } } catch { setState({ status: 'error', message: messages.error }); } }, [buildQuery, isChecking, messages, request], ); return { state, hint, isChecking, isAvailable, reset, check }; }; |