import { RiCloseLine } from '@remixicon/react' import { noop } from 'es-toolkit/function' import * as React from 'react' import { useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import Button from '@/app/components/base/button' import Input from '@/app/components/base/input' import Modal from '@/app/components/base/modal' import { ToastContext } from '@/app/components/base/toast' import { useAppContext } from '@/context/app-context' import { ownershipTransfer, sendOwnerEmail, verifyOwnerEmail, } from '@/service/common' import MemberSelector from './member-selector' type Props = { show: boolean onClose: () => void } enum STEP { start = 'start', verify = 'verify', transfer = 'transfer', } const TransferOwnershipModal = ({ onClose, show }: Props) => { const { t } = useTranslation() const { notify } = useContext(ToastContext) const { currentWorkspace, userProfile } = useAppContext() const [step, setStep] = useState(STEP.start) const [code, setCode] = useState('') const [time, setTime] = useState(0) const [stepToken, setStepToken] = useState('') const [newOwner, setNewOwner] = useState('') const [isTransfer, setIsTransfer] = useState(false) const startCount = () => { setTime(60) const timer = setInterval(() => { setTime((prev) => { if (prev <= 0) { clearInterval(timer) return 0 } return prev - 1 }) }, 1000) } const sendEmail = async () => { try { const res = await sendOwnerEmail({}) startCount() if (res.data) setStepToken(res.data) } catch (error) { notify({ type: 'error', message: `Error sending verification code: ${error ? (error as any).message : ''}`, }) } } const verifyEmailAddress = async (code: string, token: string, callback?: () => void) => { try { const res = await verifyOwnerEmail({ code, token, }) if (res.is_valid) { setStepToken(res.token) callback?.() } else { notify({ type: 'error', message: 'Verifying email failed', }) } } catch (error) { notify({ type: 'error', message: `Error verifying email: ${error ? (error as any).message : ''}`, }) } } const sendCodeToOriginEmail = async () => { await sendEmail() setStep(STEP.verify) } const handleVerifyOriginEmail = async () => { await verifyEmailAddress(code, stepToken, () => setStep(STEP.transfer)) setCode('') } const handleTransfer = async () => { setIsTransfer(true) try { await ownershipTransfer( newOwner, { token: stepToken, }, ) globalThis.location.reload() } catch (error) { notify({ type: 'error', message: `Error ownership transfer: ${error ? (error as any).message : ''}`, }) } finally { setIsTransfer(false) } } return (
{step === STEP.start && ( <>
{t('members.transferModal.title', { ns: 'common' })}
{t('members.transferModal.warning', { ns: 'common', workspace: currentWorkspace.name.replace(/'/g, '’') })}
{t('members.transferModal.warningTip', { ns: 'common' })}
}} values={{ email: userProfile.email }} />
)} {step === STEP.verify && ( <>
{t('members.transferModal.verifyEmail', { ns: 'common' })}
}} values={{ email: userProfile.email }} />
{t('members.transferModal.verifyContent2', { ns: 'common' })}
{t('members.transferModal.codeLabel', { ns: 'common' })}
setCode(e.target.value)} maxLength={6} />
{t('members.transferModal.resendTip', { ns: 'common' })} {time > 0 && ( {t('members.transferModal.resendCount', { ns: 'common', count: time })} )} {!time && ( {t('members.transferModal.resend', { ns: 'common' })} )}
)} {step === STEP.transfer && ( <>
{t('members.transferModal.title', { ns: 'common' })}
{t('members.transferModal.warning', { ns: 'common', workspace: currentWorkspace.name.replace(/'/g, '’') })}
{t('members.transferModal.warningTip', { ns: 'common' })}
{t('members.transferModal.transferLabel', { ns: 'common' })}
)}
) } export default TransferOwnershipModal