import { useEffect, useState } from 'react'; import type { AllowedProfileVisibility } from '../../api/user'; import { httpPost } from '../../lib/http'; import { useToast } from '../../hooks/use-toast'; import { CheckIcon, Loader2, X } from 'lucide-react'; import { useDebounceValue } from '../../hooks/use-debounce.ts'; type ProfileUsernameProps = { username: string; setUsername: (username: string) => void; profileVisibility: AllowedProfileVisibility; currentUsername?: string; }; export function ProfileUsername(props: ProfileUsernameProps) { const { username, setUsername, profileVisibility, currentUsername } = props; const toast = useToast(); const [isLoading, setIsLoading] = useState(false); const [isUnique, setIsUnique] = useState(null); const debouncedUsername = useDebounceValue(username, 500); useEffect(() => { checkIsUnique(debouncedUsername).then(); }, [debouncedUsername]); const checkIsUnique = async (username: string) => { if (isLoading || !username) { return; } if (username.length < 3) { setIsUnique(false); return; } if (currentUsername && username === currentUsername && isUnique !== false) { setIsUnique(true); return; } setIsLoading(true); const { response, error } = await httpPost<{ isUnique: boolean; }>(`${import.meta.env.PUBLIC_API_URL}/v1-check-is-unique-username`, { username, }); if (error || !response) { setIsUnique(null); setIsLoading(false); toast.error(error?.message || 'Something went wrong. Please try again.'); return; } setIsUnique(response.isUnique); setIsLoading(false); }; const USERNAME_REGEX = /^[a-zA-Z0-9]*$/; const isUserNameValid = (value: string) => USERNAME_REGEX.test(value) && value.length <= 20; return (
roadmap.sh/u/
{ // only allow letters, numbers const keyCode = e.key; if ( !isUserNameValid(keyCode) && !['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight'].includes( keyCode, ) ) { e.preventDefault(); } }} onInput={(e) => { const value = (e.target as HTMLInputElement).value?.trim(); if (!isUserNameValid(value)) { return; } setUsername((e.target as HTMLInputElement).value.toLowerCase()); }} required={profileVisibility === 'public'} /> {username && ( {isLoading ? ( ) : isUnique === false ? ( ) : isUnique === true ? ( ) : null} )}
); }