import { useCallback, useEffect, useState } from 'react'; import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, ListItem, ListItemIcon, ListItemText, List, TextField, Typography, useTheme, } from '@mui/material'; import { Label } from './Group/AddGroup'; import { Spacer } from '../common/Spacer'; import { getBaseApiReact } from '../App'; import { getFee } from '../background'; import RadioButtonCheckedIcon from '@mui/icons-material/RadioButtonChecked'; import { subscribeToEvent, unsubscribeFromEvent } from '../utils/events'; import { BarSpinner } from '../common/Spinners/BarSpinner/BarSpinner'; import CheckIcon from '@mui/icons-material/Check'; import ErrorIcon from '@mui/icons-material/Error'; import { useSetAtom } from 'jotai'; import { txListAtom } from '../atoms/global'; import { useTranslation } from 'react-i18next'; enum Availability { NULL = 'null', LOADING = 'loading', AVAILABLE = 'available', NOT_AVAILABLE = 'not-available', } export const RegisterName = ({ setOpenSnack, setInfoSnack, userInfo, show, balance, }) => { const setTxList = useSetAtom(txListAtom); const [isOpen, setIsOpen] = useState(false); const [registerNameValue, setRegisterNameValue] = useState(''); const [isLoadingRegisterName, setIsLoadingRegisterName] = useState(false); const [isNameAvailable, setIsNameAvailable] = useState( Availability.NULL ); const [nameFee, setNameFee] = useState(null); const theme = useTheme(); const { t } = useTranslation(['auth', 'core', 'group']); const checkIfNameExisits = async (name) => { if (!name?.trim()) { setIsNameAvailable(Availability.NULL); return; } setIsNameAvailable(Availability.LOADING); try { const res = await fetch(`${getBaseApiReact()}/names/` + name); const data = await res.json(); if (data?.message === 'name unknown') { setIsNameAvailable(Availability.AVAILABLE); } else { setIsNameAvailable(Availability.NOT_AVAILABLE); } } catch (error) { console.error(error); } }; // Debounce logic useEffect(() => { const handler = setTimeout(() => { checkIfNameExisits(registerNameValue); }, 500); // Cleanup timeout if searchValue changes before the timeout completes return () => { clearTimeout(handler); }; }, [registerNameValue]); const openRegisterNameFunc = useCallback( (e) => { setIsOpen(true); }, [setIsOpen] ); useEffect(() => { subscribeToEvent('openRegisterName', openRegisterNameFunc); return () => { unsubscribeFromEvent('openRegisterName', openRegisterNameFunc); }; }, [openRegisterNameFunc]); useEffect(() => { const nameRegistrationFee = async () => { try { const fee = await getFee('REGISTER_NAME'); setNameFee(fee?.fee); } catch (error) { console.error(error); } }; nameRegistrationFee(); }, []); const registerName = async () => { try { if (!userInfo?.address) throw new Error( t('core:message.error.address_not_found', { postProcess: 'capitalizeFirstChar', }) ); if (!registerNameValue) throw new Error( t('core:action.enter_name', { postProcess: 'capitalizeFirstChar', }) ); const fee = await getFee('REGISTER_NAME'); await show({ message: t('core:message.question.register_name', { postProcess: 'capitalizeFirstChar', }), publishFee: fee.fee + ' QORT', }); setIsLoadingRegisterName(true); new Promise((res, rej) => { window .sendMessage('registerName', { name: registerNameValue, }) .then((response) => { if (!response?.error) { res(response); setIsLoadingRegisterName(false); setInfoSnack({ type: 'success', message: t('group:message.success.registered_name', { postProcess: 'capitalizeFirstChar', }), }); setIsOpen(false); setRegisterNameValue(''); setOpenSnack(true); setTxList((prev) => [ { ...response, type: 'register-name', label: t('group:message.success.registered_name_label', { postProcess: 'capitalizeFirstChar', }), labelDone: t( 'group:message.success.registered_name_success', { postProcess: 'capitalizeFirstChar', } ), done: false, }, ...prev.filter((item) => !item.done), ]); return; } setInfoSnack({ type: 'error', message: response?.error, }); setOpenSnack(true); rej(response.error); }) .catch((error) => { setInfoSnack({ type: 'error', message: error.message || t('core:message.error.generic', { postProcess: 'capitalizeFirstChar', }), }); setOpenSnack(true); rej(error); }); }); } catch (error) { if (error?.message) { setOpenSnack(true); setInfoSnack({ type: 'error', message: error?.message, }); } } finally { setIsLoadingRegisterName(false); } }; return ( {'Register name'} setRegisterNameValue(e.target.value)} value={registerNameValue} placeholder="Choose a name" /> {(!balance || (nameFee && balance && balance < nameFee)) && ( <> {t('core:message.generic.name_registration', { balance: balance ?? 0, fee: { nameFee }, postProcess: 'capitalizeFirstChar', })} )} {isNameAvailable === Availability.AVAILABLE && ( {t('core:message.generic.name_available', { name: registerNameValue, postProcess: 'capitalizeFirstChar', })} )} {isNameAvailable === Availability.NOT_AVAILABLE && ( {t('core:message.generic.name_unavailable', { name: registerNameValue, postProcess: 'capitalizeFirstChar', })} )} {isNameAvailable === Availability.LOADING && ( {t('core:message.generic.name_checking', { postProcess: 'capitalizeFirstChar', })} )} {t('core:message.generic.name_benefits', { postProcess: 'capitalizeFirstChar', })} ); };