Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 1x 9x 9x 9x 9x 9x 9x 9x 9x 4x 1x 9x 2x 2x 2x 2x 2x 1x 9x 9x 2x | import { useEffect, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { Button } from '@core/components/ui/button'
import { Input } from '@core/components/ui/input'
import { Card, CardHeader, CardTitle, CardContent, CardDescription } from '@core/components/ui/card'
import { Label } from '@core/components/ui/label'
import { useStaffAuth } from '../hooks/useStaffAuth'
import { useEvent } from '@features/events/context/EventContext'
export const StaffLoginPage = () => {
const { t } = useTranslation('common')
const { event } = useEvent()
const { login, isLoading, isStaffAuthenticated } = useStaffAuth()
const navigate = useNavigate()
const { slug } = useParams<{ slug: string }>()
const [code, setCode] = useState('')
const [error, setError] = useState<string | null>(null)
useEffect(() => {
if (event && isStaffAuthenticated(event.id) && slug) {
navigate(`/${slug}/staff/collect`)
}
}, [event, isStaffAuthenticated, navigate, slug])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError(null)
Iif (!event) return
const result = await login(code, event.id)
if (!result.success) {
setError(result.error || 'Authentication failed')
}
}
Iif (!event) return null
return (
<div
className="flex items-center justify-center min-h-screen p-4"
style={{ backgroundColor: 'var(--auth-page-bg)' }}
>
<Card
className="w-full max-w-md backdrop-blur-md shadow-xl border-t rounded-3xl overflow-hidden"
style={{
borderRadius: 'var(--auth-card-radius)',
borderColor: 'var(--auth-input-border)',
boxShadow: 'var(--auth-card-shadow)',
}}
>
<CardHeader>
<CardTitle
className="text-2xl text-center"
style={{ color: 'var(--auth-title-color)' }}
>
{t('staff.login.title', 'Staff Access')}
</CardTitle>
<CardDescription
className="text-center"
style={{ color: 'var(--auth-subtitle-color)' }}
>
{t('staff.login.subtitle', 'Enter your PIN to start collecting donations')}
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-6">
<div className="space-y-2 text-center">
<Label
htmlFor="code"
className="text-lg"
style={{ color: 'var(--auth-label-color)' }}
>
{t('staff.login.pin_label', 'PIN Code')}
</Label>
<Input
id="code"
type="text"
inputMode="numeric"
pattern="[0-9]*"
placeholder="••••"
className="h-16 text-3xl text-center tracking-widest font-mono"
value={code}
onChange={(e) => setCode(e.target.value)}
autoFocus
style={{
backgroundColor: 'var(--auth-input-bg)',
color: 'var(--auth-input-text)',
borderColor: 'var(--auth-input-border)',
}}
/>
{error && <p className="text-sm text-red-500 mt-2">{error}</p>}
</div>
<Button
type="submit"
className="w-full h-12 text-lg"
disabled={isLoading || !code}
style={{
backgroundColor: 'var(--auth-button-bg)',
color: 'var(--auth-button-text)',
}}
>
{isLoading
? t('staff.login.loading', 'Connecting...')
: t('staff.login.submit', 'Connect')}
</Button>
</form>
</CardContent>
</Card>
</div>
)
}
|