import { useState, useEffect, useCallback } from 'react'; import { supabase } from '@/lib/supabaseClient'; import { usernameSchema } from '@/lib/validation'; import { useDebounce } from './useDebounce'; export type UsernameValidationState = { isValid: boolean; isAvailable: boolean | null; isChecking: boolean; error: string | null; }; export function useUsernameValidation(username: string, currentUsername?: string) { const [state, setState] = useState({ isValid: false, isAvailable: null, isChecking: false, error: null, }); const debouncedUsername = useDebounce(username, 500); const checkUsernameAvailability = useCallback(async (normalizedUsername: string) => { try { const { data, error } = await supabase .from('profiles') .select('username') .eq('username', normalizedUsername) .maybeSingle(); if (error) throw error; const isAvailable = !data; setState({ isValid: isAvailable, isAvailable, isChecking: false, error: isAvailable ? null : 'Username is already taken', }); } catch (error: unknown) { setState({ isValid: false, isAvailable: null, isChecking: false, error: 'Error checking username availability', }); } }, []); useEffect(() => { if (!debouncedUsername || debouncedUsername === currentUsername) { setState({ isValid: debouncedUsername === currentUsername, isAvailable: null, isChecking: false, error: null, }); return; } // Validate format first const validation = usernameSchema.safeParse(debouncedUsername); if (!validation.success) { setState({ isValid: false, isAvailable: null, isChecking: false, error: validation.error.issues[0].message, }); return; } // Check availability setState(prev => ({ ...prev, isChecking: true, error: null })); checkUsernameAvailability(validation.data); }, [debouncedUsername, currentUsername, checkUsernameAvailability]); return state; }