import { CheckmarkIcon } from '@/assets' import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar' import { useModalSearchParams } from '@/hooks/useModalSearchParams' import { swicCall } from '@/modules/swic' import { Button } from '@/shared/Button/Button' import { Input } from '@/shared/Input/Input' import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner' import { Modal } from '@/shared/Modal/Modal' import { selectKeys } from '@/store' import { useAppSelector } from '@/store/hooks/redux' import { MODAL_PARAMS_KEYS } from '@/types/modal' import { DOMAIN } from '@/utils/consts' import { fetchNip05 } from '@/utils/helpers/helpers' import { Stack, Typography, useTheme } from '@mui/material' import { ChangeEvent, Fragment, useCallback, useEffect, useState } from 'react' import { useParams } from 'react-router-dom' import { useDebounce } from 'use-debounce' import { StyledSettingContainer } from './styled' import { SectionTitle } from '@/shared/SectionTitle/SectionTitle' export const ModalEditName = () => { const keys = useAppSelector(selectKeys) const notify = useEnqueueSnackbar() const { npub = '' } = useParams<{ npub: string }>() const key = keys.find((k) => k.npub === npub) const name = key?.name || '' const { palette } = useTheme() const { getModalOpened, createHandleCloseReplace } = useModalSearchParams() const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.EDIT_NAME) const handleCloseModal = createHandleCloseReplace(MODAL_PARAMS_KEYS.EDIT_NAME) const [enteredName, setEnteredName] = useState('') const [debouncedName] = useDebounce(enteredName, 300) const isNameEqual = debouncedName === name const [receiverNpub, setReceiverNpub] = useState('') const [isAvailable, setIsAvailable] = useState(true) const [isChecking, setIsChecking] = useState(false) const [isLoading, setIsLoading] = useState(false) const [isTransferLoading, setIsTransferLoading] = useState(false) const checkIsUsernameAvailable = useCallback(async () => { if (!debouncedName.trim().length) return undefined try { setIsChecking(true) const npubNip05 = await fetchNip05(`${debouncedName}@${DOMAIN}`) setIsAvailable(!npubNip05 || npubNip05 === npub) setIsChecking(false) } catch (error) { setIsAvailable(true) setIsChecking(false) } }, [debouncedName, npub]) useEffect(() => { checkIsUsernameAvailable() }, [checkIsUsernameAvailable]) useEffect(() => { setEnteredName(name) return () => { if (isModalOpened) { setEnteredName('') setReceiverNpub('') } } // eslint-disable-next-line }, [isModalOpened]) const handleNameChange = (e: ChangeEvent) => setEnteredName(e.target.value) const handleReceiverNpubChange = (e: ChangeEvent) => setReceiverNpub(e.target.value) const getInputHelperText = () => { if (!debouncedName.trim().length || isNameEqual) return '' if (isChecking) return 'Loading...' if (!isAvailable) return 'Already taken' return ( Available ) } const inputHelperText = getInputHelperText() const getHelperTextColor = useCallback(() => { if (!debouncedName || isChecking || isNameEqual) return palette.textSecondaryDecorate.main return isAvailable ? palette.success.main : palette.error.main // deps }, [debouncedName, isAvailable, isChecking, isNameEqual, palette]) const isNpubExists = npub.trim().length && keys.some((key) => key.npub === npub) if (isModalOpened && !isNpubExists) { handleCloseModal() return null } const isEditButtonDisabled = isNameEqual || !isAvailable || isChecking || isLoading || !enteredName.trim().length const isTransferButtonDisabled = !name.length || !receiverNpub.trim().length || isTransferLoading const handleEditName = async () => { if (isEditButtonDisabled) return try { setIsLoading(true) await swicCall('editName', npub, enteredName) notify('Username updated!', 'success') setIsLoading(false) } catch (error: any) { setIsLoading(false) notify(error?.message || 'Failed to edit username!', 'error') } } const handleTransferName = async () => { if (isTransferButtonDisabled) return try { setIsTransferLoading(true) await swicCall('transferName', npub, enteredName, receiverNpub) notify('Username transferred!', 'success') setIsTransferLoading(false) setEnteredName('') } catch (error: any) { setIsTransferLoading(false) notify(error?.message || 'Failed to transfer username!', 'error') } } return ( Change name @{DOMAIN}} helperText={inputHelperText} onChange={handleNameChange} value={enteredName} helperTextProps={{ sx: { '&.helper_text': { color: getHelperTextColor(), }, }, }} /> Transfer name ) }