2026-01-13 14:49:19 +01:00

148 lines
5.4 KiB
TypeScript

import { useState } from 'react'
import { CreateAccountModal } from '../CreateAccountModal'
import { RecoveryStep } from '../CreateAccountModalSteps'
import { UnlockAccountModal } from '../UnlockAccountModal'
import { t } from '@/lib/i18n'
export function NoAccountView(): React.ReactElement {
const [showImportModal, setShowImportModal] = useState(false)
const [showRecoveryStep, setShowRecoveryStep] = useState(false)
const [showUnlockModal, setShowUnlockModal] = useState(false)
const [recoveryPhrase, setRecoveryPhrase] = useState<string[]>([])
const [npub, setNpub] = useState('')
const [generating, setGenerating] = useState(false)
const [error, setError] = useState<string | null>(null)
const handleGenerate = (): void => {
void generateNoAccount({ setGenerating, setError, setRecoveryPhrase, setNpub, setShowRecoveryStep })
}
const handleRecoveryContinue = (): void => transitionToUnlock({ setShowRecoveryStep, setShowUnlockModal })
const handleUnlockSuccess = (): void => resetNoAccountAfterUnlock({ setShowUnlockModal, setRecoveryPhrase, setNpub })
const handleImportSuccess = (): void => {
setShowImportModal(false)
setShowUnlockModal(true)
}
return (
<NoAccountCard
error={error}
generating={generating}
onGenerate={handleGenerate}
onImport={() => setShowImportModal(true)}
modals={
<NoAccountModals
showImportModal={showImportModal}
onCloseImport={() => setShowImportModal(false)}
onImportSuccess={handleImportSuccess}
showRecoveryStep={showRecoveryStep}
recoveryPhrase={recoveryPhrase}
npub={npub}
onRecoveryContinue={handleRecoveryContinue}
showUnlockModal={showUnlockModal}
onUnlockSuccess={handleUnlockSuccess}
onCloseUnlock={() => setShowUnlockModal(false)}
/>
}
/>
)
}
function NoAccountActionButtons(params: { onGenerate: () => void; onImport: () => void }): React.ReactElement {
return (
<div className="flex flex-col gap-3 w-full max-w-xs">
<button
type="button"
onClick={params.onGenerate}
className="px-6 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan"
>
{t('account.create.generateButton')}
</button>
<button
type="button"
onClick={params.onImport}
className="px-6 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg font-medium transition-colors"
>
{t('account.create.importButton')}
</button>
</div>
)
}
function NoAccountCard(params: {
error: string | null
generating: boolean
onGenerate: () => void
onImport: () => void
modals: React.ReactElement
}): React.ReactElement {
return (
<div className="border border-neon-cyan/20 rounded-lg p-6 bg-cyber-dark/50">
<div className="flex flex-col items-center gap-4">
<p className="text-center text-cyber-accent mb-2">Créez un compte ou importez votre clé secrète pour commencer</p>
{params.error ? <p className="text-sm text-red-400">{params.error}</p> : null}
<NoAccountActionButtons onGenerate={params.onGenerate} onImport={params.onImport} />
{params.generating ? <p className="text-cyber-accent text-sm">Génération du compte...</p> : null}
{params.modals}
</div>
</div>
)
}
function NoAccountModals(params: {
showImportModal: boolean
onImportSuccess: () => void
onCloseImport: () => void
showRecoveryStep: boolean
recoveryPhrase: string[]
npub: string
onRecoveryContinue: () => void
showUnlockModal: boolean
onUnlockSuccess: () => void
onCloseUnlock: () => void
}): React.ReactElement {
return (
<>
{params.showImportModal ? <CreateAccountModal onSuccess={params.onImportSuccess} onClose={params.onCloseImport} initialStep="import" /> : null}
{params.showRecoveryStep ? <RecoveryStep recoveryPhrase={params.recoveryPhrase} npub={params.npub} onContinue={params.onRecoveryContinue} /> : null}
{params.showUnlockModal ? <UnlockAccountModal onSuccess={params.onUnlockSuccess} onClose={params.onCloseUnlock} /> : null}
</>
)
}
async function generateNoAccount(params: {
setGenerating: (value: boolean) => void
setError: (value: string | null) => void
setRecoveryPhrase: (value: string[]) => void
setNpub: (value: string) => void
setShowRecoveryStep: (value: boolean) => void
}): Promise<void> {
params.setGenerating(true)
params.setError(null)
try {
const { nostrAuthService } = await import('@/lib/nostrAuth')
const result = await nostrAuthService.createAccount()
params.setRecoveryPhrase(result.recoveryPhrase)
params.setNpub(result.npub)
params.setShowRecoveryStep(true)
} catch (e) {
params.setError(e instanceof Error ? e.message : t('account.create.error.failed'))
} finally {
params.setGenerating(false)
}
}
function transitionToUnlock(params: { setShowRecoveryStep: (value: boolean) => void; setShowUnlockModal: (value: boolean) => void }): void {
params.setShowRecoveryStep(false)
params.setShowUnlockModal(true)
}
function resetNoAccountAfterUnlock(params: {
setShowUnlockModal: (value: boolean) => void
setRecoveryPhrase: (value: string[]) => void
setNpub: (value: string) => void
}): void {
params.setShowUnlockModal(false)
params.setRecoveryPhrase([])
params.setNpub('')
}