mnemo_cards/mnemo_cards_admin/src/pages/LoginPage.tsx
Dmitry 1e424031dd
Some checks are pending
Deploy Admin Panel / Deploy Admin Panel (push) Waiting to run
Deploy Admin Panel / Admin Panel Verification (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Waiting to run
dockerfiles
2025-12-11 05:04:03 +03:00

128 lines
4.1 KiB
TypeScript

import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useMutation } from '@tanstack/react-query'
import { toast } from 'sonner'
import { useAuthStore } from '@/stores/authStore'
import { authApi } from '@/api/auth'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Label } from '@/components/ui/label'
export default function LoginPage() {
const navigate = useNavigate()
const { login } = useAuthStore()
const [code, setCode] = useState('')
const [step, setStep] = useState<'request' | 'verify'>('request')
// Request code mutation
const requestCodeMutation = useMutation({
mutationFn: () => authApi.requestCode(),
onSuccess: (data) => {
if (data.success) {
toast.success('Code sent to Telegram!')
setStep('verify')
} else {
toast.error(data.message || 'Failed to send code')
}
},
onError: (error: any) => {
toast.error(error.response?.data?.message || 'Failed to send code')
},
})
// Verify code mutation
const verifyCodeMutation = useMutation({
mutationFn: (code: string) => authApi.verifyCode(code),
onSuccess: (data: any) => {
login(data.token, data.user)
toast.success('Welcome back!')
navigate('/')
},
onError: (error: any) => {
toast.error(error.response?.data?.message || 'Invalid code')
},
})
const handleRequestCode = () => {
requestCodeMutation.mutate()
}
const handleVerifyCode = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (!code.trim()) {
toast.error('Please enter verification code')
return
}
verifyCodeMutation.mutate(code.trim())
}
const handleBack = () => {
setStep('request')
setCode('')
}
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<Card className="w-full max-w-md">
<CardHeader className="space-y-1">
<CardTitle className="text-2xl font-bold text-center">
Mnemo Cards Admin
</CardTitle>
<CardDescription className="text-center">
{step === 'request'
? 'Click the button below to receive a verification code'
: 'Enter the 6-digit code sent to admin Telegram accounts'
}
</CardDescription>
</CardHeader>
<CardContent>
{step === 'request' ? (
<div className="space-y-4">
<Button
onClick={handleRequestCode}
className="w-full"
disabled={requestCodeMutation.isPending}
>
{requestCodeMutation.isPending ? 'Sending...' : 'Send Code'}
</Button>
</div>
) : (
<form onSubmit={handleVerifyCode} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="code">Verification Code</Label>
<Input
id="code"
type="text"
placeholder="Enter 6-digit code"
value={code}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setCode(e.target.value)}
maxLength={6}
disabled={verifyCodeMutation.isPending}
/>
</div>
<div className="flex space-x-2">
<Button
type="button"
variant="outline"
onClick={handleBack}
disabled={verifyCodeMutation.isPending}
className="flex-1"
>
Request New Code
</Button>
<Button
type="submit"
disabled={verifyCodeMutation.isPending}
className="flex-1"
>
{verifyCodeMutation.isPending ? 'Verifying...' : 'Verify'}
</Button>
</div>
</form>
)}
</CardContent>
</Card>
</div>
)
}